2016-03-15 59 views
2

我想在我的c#programm中提取動畫gif的個別幀。GIF到PNG:只提取第一幀

它爲每個幀創建一個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"); 

有人可以請給我解釋一下,爲什麼這個作品和原代碼執行不?
非常感謝!

回答

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); 
    } 
}