You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Delphi 7中将双列伺服动画GIF拆分为两个独立序列?

Delphi 7拆分GIF帧为左右两半的代码修改

我正在开发与ATMEL 2560通信的Delphi程序,该设备接收指令控制伺服电机运动并将位置反馈到程序的Edit框,这部分功能运行正常。现在需要实现图形化展示,找到一张包含两列伺服动画的GIF:左列位置伺服在42帧内完成-90°到+90°再返回-90°的运动;右列旋转伺服在42帧内完成整圈旋转,两者同步。

我是Delphi动画开发新手,已经在Delphi 7 Enterprise(XP SP4)中安装了GIFIMAGE单元,能打开GIF、提取单帧并保存为BMP,但不知道如何将每帧拆分为左右两半,请帮忙修改代码。

原代码:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, GifImage, XPman, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
     Gif : TGifImage;

    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1 : TForm1;
  BMP   : TBitmap;
  Curdir : String;


implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
VAR
   I : Integer;

begin
   Curdir := 'g:\servo\';
   GIF := TGifImage.Create();
   Gif.LoadFromFile(Curdir + 'servos-1.gif');
   Bmp := TBitmap.Create;
   Bmp.PixelFormat := pf24bit;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
   BMP.Free;
   GIF.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
VAR
   i  : Integer;
begin
//   Bmp.Width := Gif.Width div 2;
   Bmp.Height := Gif.Height;
   For i := 0 to Gif.Images.Count-1 do
     begin
        Bmp.Width := Gif.Width div 2;
        Bmp.Assign(Gif.Images.SubImages[i].Bitmap);
        Bmp.SaveToFile(Curdir + 'Serv' + IntToStr(i) + '.bmp');
     END;
end;

END.

修改后的代码:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, GifImage, XPman, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
     Gif : TGifImage;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1 : TForm1;
  BMPLeft, BMPRight : TBitmap; // 分别存储左右两半的帧位图
  Curdir : String;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
   Curdir := 'g:\servo\';
   GIF := TGifImage.Create();
   Gif.LoadFromFile(Curdir + 'servos-1.gif');
   
   // 初始化左半帧位图
   BMPLeft := TBitmap.Create;
   BMPLeft.PixelFormat := pf24bit;
   BMPLeft.Width := Gif.Width div 2;
   BMPLeft.Height := Gif.Height;

   // 初始化右半帧位图
   BMPRight := TBitmap.Create;
   BMPRight.PixelFormat := pf24bit;
   BMPRight.Width := Gif.Width div 2;
   BMPRight.Height := Gif.Height;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
   BMPLeft.Free;
   BMPRight.Free;
   GIF.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
VAR
   i  : Integer;
   FrameBmp: TBitmap;
begin
   FrameBmp := TBitmap.Create;
   try
      FrameBmp.PixelFormat := pf24bit;
      For i := 0 to Gif.Images.Count-1 do
      begin
         // 加载当前GIF帧到临时位图
         FrameBmp.Assign(Gif.Images.SubImages[i].Bitmap);

         // 复制左半区域到BMPLeft
         BitBlt(BMPLeft.Canvas.Handle, 0, 0, BMPLeft.Width, BMPLeft.Height,
                FrameBmp.Canvas.Handle, 0, 0, SRCCOPY);
         BMPLeft.SaveToFile(Curdir + 'ServoLeft_' + IntToStr(i) + '.bmp');

         // 复制右半区域到BMPRight
         BitBlt(BMPRight.Canvas.Handle, 0, 0, BMPRight.Width, BMPRight.Height,
                FrameBmp.Canvas.Handle, BMPLeft.Width, 0, SRCCOPY);
         BMPRight.SaveToFile(Curdir + 'ServoRight_' + IntToStr(i) + '.bmp');
      END;
   finally
      FrameBmp.Free; // 确保临时位图资源释放
   end;
end;

END.

关键修改说明

  • 新增BMPLeft和BMPRight两个位图对象,分别存储每帧的左右两半
  • 使用BitBltAPI精确复制位图区域:
    • 左半帧:从原帧的(0,0)位置复制到BMPLeft
    • 右半帧:从原帧的(原宽度/2, 0)位置复制到BMPRight
  • 添加临时位图FrameBmp避免重复赋值时的资源冲突,通过try-finally确保资源安全释放

内容的提问来源于stack exchange,提问作者Kristian Sander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 12:10:15