The Image
is not saving duplicate frames, so you have to take the time of each frame into account. Here is some sample code based on this book in Windows Programming on how to get all the frames and the correct duration. An example:
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;
}
}
We need a structure to save the Bitmap and duration for each Frame
//Class to store each frame
public class Frame
{
public Bitmap Image { get; set; }
public int Duration { get; set;}
}
The code will load a Bitmap
, check whether it is a multi-frame animated GIF
. It then loops though all the frames to construct a list of separate Frame
objects that hold the bitmap and duration of each frame. Simple use:
var frameList = Gif.LoadAnimatedGif ("a.gif");
var i = 0;
foreach(var frame in frameList)
frame.Image.Save ("frame_" + i++ + ".png");