How to extract frames from this GIF image? (Access violation in TGIFRenderer.Draw)

4

I have this functions that extracts frames from animated GIFs. It works with all GIFs except this one: enter image description here

{ Loads a GIF. Returns a list of BMP frames }
function GetGifFrames(GifFile: string): TObjectList;
var
  GIF: TGIFImage;
  TempFrame: TBitmap; 
  Frame: TBitmap;
  Counter: Integer;
  GR: TGIFRenderer;
begin
 { Load GIF }
 GIF := TGIFImage.Create;
 TRY
  TRY
   Gif.Animate := FALSE;
   GIF.LoadFromFile(GifFile);
  EXCEPT
    MesajError('Cannot load '+ GifFile);
    EXIT(NIL);
  END;

  if Gif.Images.Count= 1 then
   begin
     MsgError('This is not an animated GIF'+ CRLF+ GifFile);
     EXIT(NIL);
   end;

  Result:= TObjectList.Create;
  Result.OwnsObjects:= TRUE;                                   { Array of images }

  { GIF render }
  TempFrame:= TBitmap.Create;
  GR:= TGIFRenderer.Create(GIF);                               { GIF render }
  TRY
   TempFrame.SetSize(GIF.Width, GIF.Height);

   for Counter:= 0 to GIF.Images.Count-1 DO
    begin
      { Skip bad frames }
      if GIF.Images[Counter].Empty
      then Continue;

      { Create new frame }
      Frame:= TBitmap.Create;
      Frame.SetSize(GIF.Width, GIF.Height);
      GR.Draw(TempFrame.Canvas, TempFrame.Canvas.ClipRect);   <---------- AV here   { Transfer image from GIF to BMP }     
      Frame.Assign(TempFrame);
      Result.Add(Frame);                                       { Add to list of bitmap frames }
      GR.NextFrame;                                            { Advance }
    end;

  FINALLY
   FreeAndNil(GR);
   FreeAndNil(TempFrame);
  END;

  FINALLY
   FreeAndNil(GIF);
 END;
end;

I have an AV on the line indicated above

Debugger Exception Notification Project Tester.exe raised exception class $C0000005 with message 'access violation at 0x005d3924: read of address 0x0000002c'.

Update: Compilable tester here or here.

The stack trace is:

   GetGifFrames('C:\Test gif\err.gif')
   GIFImg.TGIFRenderer.Draw($7EFA9070,(0, 0, 108, 146, (0, 0), (108, 146)))
   GIFImg.TGIFRenderer.GetBitmap
   GIFImg.TGIFRenderer.RenderFrame

Here in Render frame it crashes on this line:

PreviousBuffer.Canvas.CopyRect(PreviousBuffer.Canvas.ClipRect, Buffer.Canvas, Buffer.Canvas.ClipRect);

This is because PreviousBuffer is NIL!!!!

How to fix this?

delphi
graphics
gif
delphi-xe7
asked on Stack Overflow Apr 6, 2016 by Z80 • edited Apr 7, 2016 by Z80

1 Answer

2

One of the properties of a frame in a GIF file is the DisposalMethod which defines how the image in the frame should be disposed of in preparation of the next frame. In the original file ("Sansanimated.gif" link at the top of the post) this is set to dmNoDisposal for all 13 frames. This works as such in your code without problems. In the file "err.gif" the two frames both have dmPrevious which require an extra internal bitmap. This bitmap is not allocated if the GIFRenderer is not initialized as being animating.

To have the GIFRenderer properly initialized for frames with dmPrevious disposal method setting add one line

GR.Animate := True;  // <---- add this line

right after creating GR.

answered on Stack Overflow Apr 7, 2016 by Tom Brunberg • edited Apr 7, 2016 by Tom Brunberg

User contributions licensed under CC BY-SA 3.0