0

GIF アニメーションを読み込んで、フレームごとにビットマップに変換する必要があります。そのために、Drawing.Imaging ライブラリを使用して GIF ファイルをフレームごとに抽出し、各フレームをビットマップにキャストしています。

連続するフレームが同じで、ピクセルの違いがない場合を除いて、すべてが正常に機能します。ライブラリはそのようなフレームをドロップしているようです。

私は簡単なテストでその結論に達しました。最後の円が消える瞬間と新しい円がまだ表示されていない瞬間の間に一時停止して成長および縮小する円のアニメーションを作成しました。抽出したビットマップで構成されるアニメーションを再生すると、一時停止が表示されません。同じフレーム長で同じフレームの量が異なる GIF を比較すると、返される totalframescount 値が異なります。また、Web ブラウザーが同一の連続したフレームを正しく表示することも確認しました。

  public void DrawGif(Image img)
    {

        FrameDimension dimension = new FrameDimension(img.FrameDimensionsList[0]);
        int frameCountTotal = img.GetFrameCount(dimension);   

        for (int framecount = 0; framecount < frameCountTotal; framecount++)
        {
            img.SelectActiveFrame(dimension, framecount);  

            Bitmap bmp = new Bitmap(img);  //cast Image type to Bitmap

                for (int i = 0; i < 16; i++)
                {
                    for (int j = 0; j < 16; j++)
                    {
                        Color color = bmp.GetPixel(i, j);
                        DrawPixel(i, j, 0, color.R, color.G, color.B);

                    }
                }
  1. 誰かがそのような問題に遭遇しましたか?
  2. 私はC#にかなり慣れていないので、.NET lib を変更する方法はありますか?
  3. ライブラリの変更を伴わない、私が気付いていない問題の解決策があるかもしれません。

更新されたコード - 結果は同じです

 public void DrawGif(img)
     {
      int frameCountTotal = img.GetFrameCount(FrameDimension.Time);
       for (int framecount = 0; framecount < frameCountTotal; framecount++)
            {
    img.SelectActiveFrame(FrameDimension.Time, framecount); 
     Bitmap bmp = new Bitmap(img);

    for (int i = 0; i < 16; i++)
            {
                for (int j = 0; j < 16; j++)
                {
                        Color color = bmp.GetPixel(i, j);
                        DrawPixel(i, j, 0, color.R, color.G, color.B);

                }
4

1 に答える 1

2

Image重複したフレームを保存しないため、各フレームの時間を考慮する必要があります。すべてのフレームと正しい期間を取得する方法について、Windows プログラミングのこの本に基づいたサンプル コードを次に示します。例:

public class Gif
{
    public static List<Frame> LoadAnimatedGif(string path)
    {
        //If path is not found, we should throw an IO exception
        if (!File.Exists(path))
            throw new IOException("File does not exist");

        //Load the image
        var img = Image.FromFile(path);

        //Count the frames
        var frameCount = img.GetFrameCount(FrameDimension.Time);

        //If the image is not an animated gif, we should throw an
        //argument exception
        if (frameCount <= 1)
            throw new ArgumentException("Image is not animated");

        //List that will hold all the frames
        var frames = new List<Frame>();

        //Get the times stored in the gif
        //PropertyTagFrameDelay ((PROPID) 0x5100) comes from gdiplusimaging.h
        //More info on http://msdn.microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx
        var times = img.GetPropertyItem(0x5100).Value;

        //Convert the 4bit duration chunk into an int

        for (int i = 0; i < frameCount; i++)
        {
            //convert 4 bit value to integer
            var duration = BitConverter.ToInt32(times, 4*i);

            //Add a new frame to our list of frames
            frames.Add(
                new Frame()
                {
                    Image = new Bitmap(img),
                    Duration = duration
                });

            //Set the write frame before we save it
            img.SelectActiveFrame(FrameDimension.Time, i);


        }

        //Dispose the image when we're done
        img.Dispose();

        return frames;
    }
}

各フレームのビットマップと期間を保存するための構造が必要です

//Class to store each frame
public class Frame 
{ 
    public Bitmap Image { get; set; } 
    public int Duration { get; set;} 
}

コードは をロードしBitmap、それがマルチフレーム アニメーション化されているかどうかを確認しGIFます。次に、すべてのフレームをループしてFrame、各フレームのビットマップと期間を保持する個別のオブジェクトのリストを作成します。簡単な使用:

var frameList = Gif.LoadAnimatedGif ("a.gif");

var i = 0;
foreach(var frame in frameList)
    frame.Image.Save ("frame_" + i++ + ".png");
于 2013-07-18T12:36:37.693 に答える