如何将TGifImage中的帧提取为位图?

7
以下演示尝试在表单的画布上绘制GIF。但是它无法正常工作,图像不会播放。如何让它正常工作?
procedure TForm1.FormCreate(Sender: TObject);
begin
 GIF := TGIFImage.Create;
 GIF.LoadFromFile('c:\2.gif');
end;

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

procedure TForm1.Button1Click(Sender: TObject);
VAR i: Integer;
begin
 REPEAT
  for i:= 0 to GIF.Images.Count-1 DO
   begin
    DisplayGifFrame(i);
    Sleep(30);
   end;
 UNTIL FALSE;
end;


procedure TForm1.DisplayGifFrame(AIndex: Integer);
VAR
   Renderer: TGIFRenderer;
begin
 Renderer := TGIFRenderer.Create(GIF);
 TRY
  Renderer.Animate := TRUE;
  Renderer.FrameIndex := AIndex;
  Renderer.Draw(Canvas, Canvas.ClipRect); 

  {save frame in a bitmap here. save bitmap to disk}
  // xxx 
 FINALLY
  Renderer.Free;
 end;
end;

我想要实现的目标:
我想从一个GIF文件中提取所有帧,并将每一帧放入一个独立的位图中。


更新:
继续阅读:无法在动态创建的TBitmap上绘制GIF


1
那么你的问题到底是什么?你在发布的代码中遇到了什么问题?有什么不符合你的期望?试着从我们的角度阅读你的问题,记住我们对你的代码要做什么、你认为它应该做什么或任何关于它不起作用的信息一无所知。然后请编辑并添加更多细节,以便我们可以尝试帮助你。 :-) - Ken White
我不知道是谁这么快就点了踩,但请停止。在决定踩之前,请给发帖人几分钟时间回复评论并修正问题,特别是当其他人已经要求他们这样做时。@Altar:“它不起作用”对任何人都没有意义,除了你。请再次阅读我的最后一条评论。 - Ken White
问题已更新。感谢Ken平息群众的情绪 :) - Gabriel
1个回答

8

试试这个:

procedure TForm1.Button1Click(Sender: TObject);
var
  GIF: TGIFImage;
  Bitmap: TBitmap;
  I: Integer;
  GR: TGIFRenderer;
  R: TRect;
begin
  GIF := TGIFImage.Create;      
  Bitmap := TBitmap.Create;
  try
    GIF.LoadFromFile('c:\test\test.gif');
    Bitmap.SetSize(GIF.Width, GIF.Height);
    GR := TGIFRenderer.Create(GIF);
    try
      for I := 0 to GIF.Images.Count - 1 do
      begin
        if GIF.Images[I].Empty then Break;
        GR.Draw(Bitmap.Canvas, Bitmap.Canvas.ClipRect);
        GR.NextFrame;
        Bitmap.SaveToFile(Format('%.2d.bmp', [I]));
      end;
    finally
      GR.Free;
    end;  
  finally
    GIF.Free;
    Bitmap.Free;
  end;
end;

以上代码考虑了帧的Disposal方法。相关问题请参见这里

只是出于好奇,这个方法也适用于交错的 GIF 图像吗? - TLama
1
不,Update 不会有所帮助。在绘制发生之前没有需要处理的“绘制消息”。向画布上绘制实际上是即时的。Update 告诉窗口它应该立即绘制自己,但这只意味着它将绘制到它的画布上,而这正是 GR.Draw 正在做的事情。 - Rob Kennedy
3
@Altar,你在最初的Q中想要保存帧位图。我不明白你现在的目标是什么。 - kobik
@TLama,我认为你指的是“Disposal”方法,这段代码已经考虑到了它。 - kobik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接