3

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?

6
  • When you put breakpoint at line GR.Draw(TempFrame.Canvas, TempFrame.Canvas.ClipRect); what value stored in GR in TempFrame? Commented Apr 6, 2016 at 7:22
  • @ZamronyP.Juhara - Values for TempFrame.Width and Height are ok (the size of the gif 108x146). ClipRect is also Ok. Maybe this particular GIF is malformed? Commented Apr 6, 2016 at 7:35
  • 1
    Why is it so difficult to show the complete error message, don't you think there could be some valuable information? BTW, I tested your code as is with the image ("Sansanimated.gif") but no AV, nor any other error, 13 frames in TObjectList. Commented Apr 6, 2016 at 8:13
  • Read of address 0x0000002C looks like access to a nil object reference, and since you only access TempFrame and its Canvas, is either nil? Of course in your code they shouldn't, but ... Commented Apr 6, 2016 at 17:39
  • @TomBrunberg- Hi Tom. 1. Tester (DPR, PAS, DFM file) available here: s000.tinyupload.com/… There is also the compiled file (exe) that will show the AV (in case you still cannot repro in your computer). 2. I think you get 'read of address 00000000' when you try to access a nil obj. Commented Apr 6, 2016 at 18:46

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

9 Comments

Out of curiosity: What makes the code to work for all other GIFs but not for this one?
Maybe omitting Gif.Animate := FALSE; will have the same effect.
@kobik- Sorry. I don't understand
@SolarWind, You explicitly added Gif.Animate := FALSE; in your code (I don't know why you did) Have you tried removing this line?
@SolarWind Thanks! The gifs that work do not have the disposal mode set to dmPrevious. dmPrevious is mostly used for gifs that update only smaller parts of the total image in each frame. I did not have such gif among the ones on my PC.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.