2

C# プログラムでアニメーション gif の個々のフレームを抽出しようとしています。

フレームごとにpngを作成します-これは問題なく機能しますが、最初のフレームの単なるコピーの束です。私は何を間違えましたか?

Image img = Image.FromFile(path);
FrameDimension dimension = new FrameDimension(img.FrameDimensionsList[0]);
int frameCount = img.GetFrameCount(dimension);
MemoryStream memory = new MemoryStream();
for(int i = 0; i < frameCount; i++){
    img.SelectActiveFrame(dimension, i);
    ((Image)img.Clone).Save(memory, System.Drawing.Imaging.ImageFormat.Png);
    File.WriteAllBytes(myFolder + "/frame_"+i+".png", memory.ToArray());
}


更新: いくつかいじくり回した後、これを使用すると機能することがわかりました:

Bitmap bmp = new Bitmap(img);
bmp.Save(Application.dataPath + projectFolder.Substring(6) + "/frame_"+i+".png");

なぜこれが機能し、元のコードが機能しないのか、誰かが私に説明してもらえますか?
どうもありがとうございました!

4

1 に答える 1

2

主な問題は、リセットせずに同じメモリストリームに書き込んでいることだと思います。したがって、以前に抽出したすべてのファイルの内容を、それぞれの新しいフレームに効果的に書き出しています。また、各画像について、最初のフレームのみが表示されます。

最初に行うのではなく、画像ごとに新しいメモリ ストリームを割り当てる必要があります。

for(int i = 0; i < frameCount; i++)
{
    img.SelectActiveFrame(dimension, i);
    var outputPath = myFolder + "/frame_"+i+".png";
    using (var memory = new MemoryStream())
    {
        img.Save(memory, ImageFormat.Png); // cloning is not necessary
        File.WriteAllBytes(outputPath, memory.ToArray());
    }
}

一方、メモリ ストリームを作成する必要はまったくなく、ファイルに直接書き込むだけです。

var path = ...;
var dir = ...;
using (var img = Image.FromFile(path))
{
    var dimension = new FrameDimension(img.FrameDimensionsList.First());
    var frameCount = img.GetFrameCount(dimension);
    foreach (var i in Enumerable.Range(0, frameCount))
    {
        img.SelectActiveFrame(dimension, i);
        var outputFile = Path.Combine(dir, $"frame_{i:00}.png");
        img.Save(outputFile, ImageFormat.Png);
    }
}
于 2016-03-15T22:06:40.450 に答える