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

📄 unit1.~pas

📁 使用Delphi实现了对一张图片的几何变换
💻 ~PAS
📖 第 1 页 / 共 2 页
字号:
function ArcTan2(xt, yt: Single): Single;
begin
  if xt = 0 then
    if yt > 0 then
      Result := Pi / 2
    else
      Result := -(Pi / 2)
  else
  begin
    Result := ArcTan(yt / xt);
    if xt < 0 then
      Result := Pi + ArcTan(yt / xt);
  end;
end;

//实现扭曲效果的函数
procedure TForm1.bmp_twist(var Oribmp, Newbmp: TBitmap; Count: integer);
var
   fxmid, fymid,txmid, tymid,fx, fy, tx2, ty2, r, theta: Single;
   dx, dy,OFFSET,weight,total_red, total_green,total_blue: Single;
   weight_x, weight_y: array[0..1] of Single;
   ifx, ify,ty, tx,new_red, new_green,new_blue,ix, iy: Integer;
   sli, slo: PBytearray;
begin
   OFFSET := -(Pi / 2);
   dx := Oribmp.Width - 1;
   dy := Oribmp.Height - 1;
   r := Sqrt(dx * dx + dy * dy);
   tx2 := r;
   ty2 := r;
   //调整参数以移动图像的选择中心
   txmid := (Oribmp.Width - 1) / 2;
   tymid := (Oribmp.Height - 1) / 2; 
   fxmid := (Oribmp.Width - 1) / 2;
   fymid := (Oribmp.Height - 1) / 2;
   if tx2 >= Oribmp.Width then
      tx2 := Oribmp.Width - 1;
   if ty2 >= Oribmp.Height then
      ty2 := Oribmp.Height - 1;
   for ty := 0 to Round(ty2) do
   begin
      for tx := 0 to Round(tx2) do
      begin
         dx := tx - txmid;
         dy := ty - tymid;
         r := Sqrt(dx * dx + dy * dy);
         if r = 0 then
         begin
            fx := 0;
            fy := 0;
         end
         else
         begin
            theta := ArcTan2(dx, dy) - r / Count - OFFSET;
            fx := r * Cos(theta);
            fy := r * Sin(theta);
         end;
         fx := fx + fxmid;
         fy := fy + fymid;

         ify := Trunc(fy);
         ifx := Trunc(fx);
         //计算weight值
         if fy >= 0 then
         begin
            weight_y[1] := fy - ify;
            weight_y[0] := 1 - weight_y[1];
         end
         else
         begin
            weight_y[0] := -(fy - ify);
            weight_y[1] := 1 - weight_y[0];
         end;
         if fx >= 0 then
         begin
            weight_x[1] := fx - ifx;
            weight_x[0] := 1 - weight_x[1];
         end
         else
         begin
            weight_x[0] := -(fx - ifx);
            Weight_x[1] := 1 - weight_x[0];
         end;

         if ifx < 0 then
            ifx := Oribmp.Width - 1 - (-ifx mod Oribmp.Width)
         else if ifx > Oribmp.Width - 1 then
            ifx := ifx mod Oribmp.Width;
         if ify < 0 then
            ify := Oribmp.Height - 1 - (-ify mod Oribmp.Height)
         else if ify > Oribmp.Height - 1 then
            ify := ify mod Oribmp.Height;

         total_red := 0.0;
         total_green := 0.0;
         total_blue := 0.0;
         for ix := 0 to 1 do
         begin
            for iy := 0 to 1 do
            begin
               if ify + iy < Oribmp.Height then
                  sli := Oribmp.scanline[ify + iy]
               else
                  sli := Oribmp.scanline[Oribmp.Height - ify - iy];
               if ifx + ix < Oribmp.Width then
               begin
                  new_red := sli[(ifx + ix) * 3];
                  new_green := sli[(ifx + ix) * 3 + 1];
                  new_blue := sli[(ifx + ix) * 3 + 2];
               end
               else
               begin
                  new_red := sli[(Oribmp.Width - ifx - ix)
                     * 3];
                  new_green := sli[(Oribmp.Width - ifx -
                     ix) * 3 +
                     1];
                  new_blue := sli[(Oribmp.Width - ifx - ix)
                     * 3 +
                     2];
               end;
               weight := weight_x[ix] * weight_y[iy];
               total_red := total_red + new_red * weight;
               total_green := total_green + new_green *
                  weight;
               total_blue := total_blue + new_blue * weight;
            end;
         end;
         slo := Newbmp.scanline[ty];
         slo[tx * 3] := Round(total_red);
         slo[tx * 3 + 1] := Round(total_green);
         slo[tx * 3 + 2] := Round(total_blue);
      end;
   end;
end;

//波浪效果
procedure TForm1.N12Click(Sender: TObject);
begin
   //若当前无图片,则不做处理
   if (image1.Picture.Bitmap = nil) then
      showmessage('请加载图片')
   else
      //调用bmp_Wave实现图片的波浪效果
      bmp_Wave(2, 6, 2);
end;

//实现波浪效果的函数
procedure TForm1.bmp_Wave(XDIV, YDIV, RatioVal: Integer);
var
   bmp1, bmp2: Tbitmap;
   i, j, XSrc, YSrc: Integer;
begin
   //如果不需要做波浪效果,则退出
   if (XDiv = 0) or (YDiv = 0) then
      Exit;
   //创建Tbitmap对象bmp1和bmp2
   bmp1 := Tbitmap.create;
   bmp2 := Tbitmap.Create;
   //将当前图像指定给Bmp1和bmp2
   bmp2.Assign(self.Image1.Picture.Bitmap);
   bmp1.assign(self.Image1.Picture.Bitmap);
   //开始计时
   BeginTime := gettickcount;
   //开始实现波浪效果
   for i := 0 to bmp1.Width - 1 do
   begin
      for j := 0 to bmp1.Height - 1 do
      begin
         XSrc := Round(i + RatioVal * Sin(j / YDiv));
         YSrc := Round(j + RatioVal * sin(i / XDiv));
         if XSrc < 0 then
            XSrc := Width - 1 - (-XSrc mod Width)
         else if XSrc >= Width then
            XSrc := XSrc mod Width;
         if YSrc < 0 then
            YSrc := Height - 1 - (-YSrc mod Height)
         else if YSrc >= Height then
            YSrc := YSrc mod (Height - 1);
         bmp2.Canvas.Pixels[i, j] := bmp1.Canvas.Pixels[XSrc, YSrc];
      end;
   end;
   //显示变化后的图片
   self.Image1.Picture.Assign(bmp2);
   //获得结束时间
   EndTime := gettickcount;
   //计算出消耗时间
   self.StatusBar1.simpleText := '   完成时间为:' + IntToStr(EndTime -
      BeginTime) + '毫秒';
   //释放位图对象
   bmp2.Free;
   bmp1.Free;
end;

//远视图效果
procedure TForm1.Y1Click(Sender: TObject);
var
   inbmp, outbmp: Tbitmap;
begin
   //若当前无图片,则不做处理
   if Image1.Picture.Bitmap.Empty then
   begin
      ShowMessage('请加载图片');
      exit;
   end;
   //创建Tbitmap对象inbmp和outbmp
   inbmp := TBitmap.Create;
   outbmp := TBitmap.Create;
   //将当前图像指定给inbmp
   inbmp.Assign(image1.Picture.Bitmap);
   //开始计时
   BeginTime := GetTickcount;
   //调用bmp_tilt实现远视图效果
   bmp_Tilt(inbmp, outbmp, 200, 400);
   //显示变化后的图片
   image1.Picture.Bitmap.Assign(outbmp);
   image1.Invalidate;
   //获得结束时间
   EndTime := GetTickcount;
   //计算出消耗时间
   self.StatusBar1.simpleText:= '执行时间为:' +
                  inttostr(EndTime - BeginTime) + '毫秒';
   //释放位图对象
   inbmp.Free;
   outbmp.Free;
end;

//实现远视图效果的函数
procedure TForm1.bmp_Tilt(const inbmp, outbmp: TBitmap;
   const WidthTop, WidthBottom: integer);
var
   y, xWidthDiff, xWidthCurrentLine: Integer;
   d: Real;
begin
   //设定象素的显示颜色素
   outbmp.PixelFormat := inbmp.PixelFormat;
   //设置图像参数
   if WidthTop > WidthBottom then
      outbmp.Width := WidthTop
   else
      outbmp.Width := WidthBottom;
   outbmp.Height := inbmp.Height;
   outbmp.Canvas.Brush.Color := clblack;
   outbmp.Canvas.FillRect(outbmp.Canvas.ClipRect);
   outbmp.Canvas.CopyMode := cmSrcCopy;
   //缓慢并高质量地变换图像
   SetStretchBltMode(outbmp.Canvas.Handle, HALFTONE);
   //设置画刷样式的原点
   SetBrushOrgEx(outbmp.Canvas.Handle, 0, 0, nil);
   outbmp.Canvas.CopyMode := cmSrcCopy;
   d := (WidthBottom - WidthTop) / outbmp.Height;
   //开始变换
   for y := 0 to outbmp.Height - 1 do
   begin
      xWidthCurrentLine := Trunc(WidthTop + d * y);
      xWidthDiff := (outbmp.Width - xWidthCurrentLine) div 2;
      outbmp.Canvas.CopyRect(Rect(xWidthDiff, y, xWidthDiff +
         xWidthCurrentLine, y + 1),
         inbmp.Canvas, Rect(0, y, inbmp.Width, y + 1));
   end;
end;

//水平镜像
procedure TForm1.N15Click(Sender: TObject);
var
   bmp1, bmp2, bmp3: TBitmap;
   T, P: pByteArray;
   X, Y: integer;
begin
   //创建Tbitmap对象bmp1、bmp2和bmp3
   bmp1 := TBitmap.Create;
   bmp2 := TBitmap.Create;
   bmp3 := TBitmap.Create;
   //将当前图像指定给bmp1和bmp2
   bmp1.Assign(Image1.Picture.Bitmap);
   bmp2.Assign(Image1.Picture.Bitmap);
   //设置bmp3的样式
   bmp3.Width := 2 * bmp1.Width;
   bmp3.Height := Image1.Picture.Bitmap.Height;
   //开始计时
   BeginTime := GetTickcount;
   //开始变换
   for Y := 0 to bmp2.Height - 1 do
   begin
      T := bmp2.ScanLine[Y];
      P := bmp1.ScanLine[Y];
      for X := 0 to bmp2.Width - 1 do
      begin
         P[3 * X + 2] := T[3 * (bmp2.Width - 1 - X) + 2];
         P[3 * X + 1] := T[3 * (bmp2.Width - 1 - X) + 1];
         P[3 * X] := T[3 * (bmp2.Width - 1 - X)];
      end;
   end;
   bmp3.Canvas.Draw(0, 0, bmp2);
   bmp3.Canvas.Draw(bmp2.Width, 0, bmp1);
   //显示变化后的图片
   Image1.Picture.Bitmap.Assign(bmp3);
   //获得结束时间
   EndTime := GetTickcount;
   //计算出消耗时间
   self.StatusBar1.simpleText:= '执行时间为:' +
                  inttostr(EndTime - BeginTime) + '毫秒';
   //释放位图对象
   bmp1.Free;
   bmp2.Free;
   bmp3.Free;
end;

//垂直镜像
procedure TForm1.V1Click(Sender: TObject);
var
   bmp1, bmp2, bmp3: Tbitmap;
   i, j: integer;
   p, p1: pbyteArray;
begin
   //创建Tbitmap对象bmp1、bmp2和bmp3
   bmp1 := Tbitmap.Create;
   bmp2 := Tbitmap.Create;
   bmp3 := Tbitmap.Create;
   //将当前图像指定给bmp1和bmp2
   bmp1.Assign(Self.Image1.Picture.Bitmap);
   bmp2.Assign(Self.image1.Picture.Bitmap);
   //设置bmp3的样式
   bmp3.Width := bmp1.Width;
   bmp3.Height := 2 * bmp1.Height;
   //设定象素的显示颜色素
   bmp1.PixelFormat := pf24bit;
   bmp2.PixelFormat := pf24bit;
   //开始计时
   BeginTime := GetTickcount;
   //开始变换
   for j := 0 to Self.image1.Picture.Graphic.Height - 1 do
   begin
      p := bmp1.ScanLine[j];
      p1 := bmp2.ScanLine[Self.IMAGE1.Picture.Graphic.Height - 1 - j];
      for i := 0 to Self.image1.Picture.Graphic.Width - 1 do
      begin
         p[3 * i] := p1[3 * i];
         p[3 * i + 1] := p1[3 * i + 1];
         p[3 * i + 2] := p1[2 + 3 * i];
      end;
   end;
   bmp3.Canvas.Draw(0, 0, bmp2);
   bmp3.Canvas.Draw(0, bmp1.Height, bmp1);
   bmp3.PixelFormat := pf24bit;
   //显示变化后的图片
   Self.Image1.Picture.Bitmap.Assign(bmp3);
   Self.image1.picture.Bitmap.PixelFormat := pf24bit;
   //获得结束时间
   EndTime := GetTickcount;
   //计算出消耗时间
   self.StatusBar1.simpleText:= '执行时间为:' +
              inttostr(EndTime - BeginTime) + '毫秒';

   //释放位图对象
   bmp1.Free;
   bmp2.Free;
   bmp3.Free;
end;

//裁剪图像
procedure TForm1.C1Click(Sender: TObject);
var
   rgn1: Hrgn;
   Bmp1: TBitmap;
begin
   //创建Tbitmap对象bmp1
   Bmp1 := TBitmap.Create;
   //将当前图像指定给bmp1
   Bmp1.Assign(Image1.Picture.Bitmap);
   //开始计时
   BeginTime := GetTickcount;
   //创建剪切区域
   rgn1 := CreateRectRgn(40, 40, 500, 300);
   //选中剪裁区域
   SelectclipRgn(Image1.Canvas.Handle, rgn1);
   //清空图像
   Image1.Picture := nil;
   //通过拷贝将图像显示在界面上
   BitBlt(Image1.Canvas.Handle, 40, 40, 500, 300, Bmp1.Canvas.Handle, 0, 0,
      SRCCOPY);
   //获得结束时间
   EndTime := GetTickcount;
   //计算出消耗时间
   self.StatusBar1.simpleText:= '执行时间为:' +
                    inttostr(EndTime - BeginTime) + '毫秒';
   //释放位图对象
   Bmp1.Free;
end;

//还原图像
procedure TForm1.R1Click(Sender: TObject);
begin
  //还原图像
  image1.Picture.Bitmap.Assign(OldBmp);
end;

procedure TForm1.Q1Click(Sender: TObject);
begin
  //释放位图对象
  OldBmp.Free;
  Close;
end;

end.

⌨️ 快捷键说明

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