GIF 到 PNG:仅提取第一帧
GIF to PNGs: only first frame extracted
我正在尝试在我的 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");
有人可以向我解释一下,为什么这个有效而原始代码无效?
非常感谢!
我认为主要问题是您在不重置的情况下写入同一个内存流。因此,您实际上是在将所有先前提取的文件的内容写到每个新帧中。对于每个图像,只有第一帧是可见的。
您将不得不为每个图像分配一个新的内存流,而不是在一开始就这样做。
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);
}
}
我正在尝试在我的 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");
有人可以向我解释一下,为什么这个有效而原始代码无效?
非常感谢!
我认为主要问题是您在不重置的情况下写入同一个内存流。因此,您实际上是在将所有先前提取的文件的内容写到每个新帧中。对于每个图像,只有第一帧是可见的。
您将不得不为每个图像分配一个新的内存流,而不是在一开始就这样做。
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);
}
}