2016-04-06 5 views
4

私はアニメーションGIFからフレームを抽出するこの機能を持っています。これは、この1以外のすべてのGIFファイルで動作します:enter image description hereこのGIF画像からフレームを抽出する方法は? (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; 

私はメッセージ「アクセス違反で

デバッガ例外通知プロジェクトTester.exe発生した例外 クラスの$ C0000005上に示したライン上のAVを持っています0x005d3924で: アドレス0x0000002c 'の読み取り。

更新: コンパイル可能テスターherehere

スタックトレースは次のとおりです。

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

で、それはこのラインにクラッシュするフレームをレンダリングします

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

PreviousBufferがNILがあるためです!!!!

これを修正するにはどうすればよいですか?

+0

'GR.Draw(TempFrame.Canvas、TempFrame.Canvas.ClipRect);行にブレークポイントを置くと、' TempFrame'の 'GR'にはどのような値が格納されますか? –

+0

@ ZamronyP.Juhara - TempFrame.WidthとHeightの値はokです(gif 108x146のサイズ)。 ClipRectもOkです。多分この特定のGIFは形式が違うでしょうか? – Ampere

+1

完全なエラーメッセージを表示するのがなぜ難しいのですか、貴重な情報があると思わないのですか?私はあなたのコードを画像( "Sansanimated.gif")でテストしましたが、AVやその他のエラーはなく、TObjectListの13個のフレームをテストしました。 –

答えて

2

GIFファイル内のフレームのプロパティの1つは、フレーム内のイメージを次のフレームの準備にどのように処理するかを定義するDisposalMethodです。元のファイル(投稿の上部にある "Sansanimated.gif"リンク)では、13フレームすべてでdmNoDisposalに設定されています。これはあなたのコードで問題なく動作します。ファイル "err.gif"では、2つのフレームの両方に余分な内部ビットマップを必要とするdmPreviousがあります。 GIFRendererがアニメーション化されて初期化されていない場合、このビットマップは割り当てられません。 GIFRendererが正しく右GRを作成した後に1行

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

を追加設定dmPrevious廃棄方法を持つフレーム用に初期化されているように

+0

好奇心を要しない:他のすべてのGIFでは動作しますが、これは動作しません。 – Ampere

+0

'Gif。Animate:= FALSE;は同じ効果を持ちます。 – kobik

+0

@ kobik-申し訳ありません。私は分かりません – Ampere

関連する問題