2016-04-06 23 views
4

Animasyonlu GIF'lerden kareleri ayıklayan bu işlevlere sahibim. Bu biri hariç tüm GIF'lerle çalışır: enter image description hereBu GIF resminden çerçeveler nasıl çıkarılır? (Erişim ihlali TGIFRenderer.Draw)

{ 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; 

Ben mesajın 'erişim ihlali ile

Debugger İstisna Bildirim Projesi Tester.exe kaldırdı istisna sınıf $ c0000005 yukarıda belirtilen hat üzerinde bir AV var 0x005d3924: adresinin 0x0000002c 'değerini okuyun.

Güncelleme: Derlenebilir tester here veya here.

Yığın izleme:

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

olarak bu hat çöker çerçeve oluşturulma:

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

PreviousBuffer NIL olan olmasıdır !!!!

Bunu nasıl düzeltebilirim?

+0

Kesme noktasını "GR.Draw (TempFrame.Canvas, TempFrame.Canvas.ClipRect)" satırına koyduğunuzda, '' TempFrame'de 'GR' içinde depolanan değer nedir? –

+0

@ ZamronyP.Juhara - TempFrame.Width ve Height değerleri tamam (gif 108x146'nın boyutu). ClipRect de Tamam. Belki bu belirli GIF yanlış biçimlendirilmiş? – Ampere

+1

Tam hata mesajını göstermek neden bu kadar zor, bazı değerli bilgiler olabileceğini düşünmüyor musunuz? BTW, kodunuzu imgede ("Sansanimated.gif") olduğu gibi test ettim, ama AV değil, ya da başka bir hata, "TObjectList" içinde 13 kare. –

cevap

2

GIF dosyasındaki bir çerçevenin özelliklerinden biri, çerçevedeki görüntünün bir sonraki çerçevenin hazırlanmasında nasıl atılacağını tanımlayan DisposalMethod'dur. Orijinal dosyada (yayının üstündeki "Sansanimated.gif" bağlantısı) bu, 13 çerçevenin tamamı için dmNoDisposal olarak ayarlanır. Bu, kodunuzda sorunsuz çalışır. "Err.gif" dosyasında, iki çerçevede fazladan bir dahili bitmap gerektiren dmPrevious vardır. Bu bitmap, GIFRenderer'un animasyonlu olarak başlatılmamış olması durumunda ayrılmaz.

GIFRenderer düzgün sağ GR oluşturduktan sonra bir satır
GR.Animate := True; // <---- add this line 

eklemek dmPrevious bertaraf yöntemi ayarıyla çerçeveler için başlatıldı sahip olmak.

+0

Merak etme: Kodu diğer tüm GIF'ler için işe yarar kılan, ancak bunun için olmayan nedir? – Ampere

+0

Belki "Gif" kelimesini atlıyor.Animate: = FALSE; 'aynı etkiye sahip olacaktır. – kobik

+0

@ kobik- Üzgünüz. Anlamıyorum – Ampere

İlgili konular