我正在尝试在c#programm中提取动画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");
有人可以向我解释,为什么这样做有原因并且原始代码没有?
非常感谢你!
答案 0 :(得分: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);
}
}