Getting GIF image information using C#
Extracting GIF image data in .NET using C#
GIF image format is most commonly used format for online advertising, especially since all browser starting from major onces stopped supporting Flash animations because of their infamous security vulnerabilities and issues.
After going through different articles I found online, I came up with the class which exposes following GIF image properties.
Property name | Type | Description |
FileInfo | System.IO.FileInfo | FileInfo instance for the image file path |
Frames | System.Collections.Generic.IList<System.Drawing.Image> | List of Image instaces representing the animated GIF image. If there are no frmaes, cloned instace of Image class is returned |
Size | System.Drawing.Size | Width and Height of the image |
Animated | System.Boolean | Indicating wheter GIF image is animated and hase multiple frames |
Loop | System.Boolean | Indicating that animation is repeating in a loop |
AnimationDuration | System.TimeSpan | Duration in which all frmaes are displayed representing one animation loop cycle |
using System;using System.Collections.Generic;using System.Drawing;using System.Drawing.Imaging;using System.IO;namespace GifInfo{public class GifInfo{#region Filedsprivate FileInfo fileInfo;private IList<Image> frames;private Size size;private bool animated;private bool loop;private TimeSpan animationDuration;#endregion#region Propertiespublic FileInfo FileInfo{get { return this.fileInfo; } } public IList<Image> Frames { get { return this.frames; } } public Size Size { get { return this.size; } } public bool Animated { get { return this.animated; } } public bool Loop { get { return this.loop; } } public TimeSpan AnimationDuration { get { return this.animationDuration; } } #endregion #region Constructors public GifInfo(String filePath) { if (File.Exists(filePath)) { using (var image = Image.FromFile(filePath)) { this.size = new Size(image.Width, image.Height); if (image.RawFormat.Equals(ImageFormat.Gif)) { this.frames = new List<Image>(); this.fileInfo = new FileInfo(filePath); if (ImageAnimator.CanAnimate(image)) { //Get frames var dimension = new FrameDimension(image.FrameDimensionsList[0]); int frameCount = image.GetFrameCount(dimension); int index = 0; int duration = 0; for (int i = 0; i < frameCount; i++) { image.SelectActiveFrame(dimension, i); var frame = image.Clone() as Image; frames.Add(frame); var delay = BitConverter.ToInt32(image.GetPropertyItem(20736).Value, index) * 10; duration += (delay < 100 ? 100 : delay); index += 4; } this.animationDuration = TimeSpan.FromMilliseconds(duration); this.animated = true; this.loop = BitConverter.ToInt16(image.GetPropertyItem(20737).Value, 0) != 1; } else { this.frames.Add(image.Clone() as Image); } } else { throw new FormatException("Not valid GIF image format"); } } } } #endregion } }
All the calculation and heavy lifting is done on the constructor of the class in the same manner System.IO.FileInfo is implemented. Now to take this class for a spin, I used the following GIF which I downloaded from https://gifer.com/en/5m7W
class Program { static void Main(string[] args) { var path = @"C:\temp\sample.gif"; var info = new GifInfo(path); for (int i = 0; i < info.Frames.Count - 1; i++) { var frameFilePath = Path.Combine(Path.GetDirectoryName(path), $"{Path.GetFileNameWithoutExtension(path)}-{i.ToString()}.gif"); var frame = info.Frames[i]; Console.WriteLine(frameFilePath); frame.Save(frameFilePath, ImageFormat.Gif); } Console.ReadLine(); } }
This sample code will extract all animated GIF frames and save them as a separate GIF files in the same folder where original file is. The output in the console will be following
C:\temp\sample-1.gif
C:\temp\sample-2.gif
C:\temp\sample-3.gif
C:\temp\sample-4.gif
C:\temp\sample-5.gif
C:\temp\sample-6.gif
You can clearly see that this animated GIF has 7 frames and you can check all the frames images in the paths from the console output.
References
- https://msdn.microsoft.com/en-us/library/system.drawing.image(v=vs.110).aspx
- https://msdn.microsoft.com/en-us/library/system.drawing.bitmap(v=vs.110).aspx
Disclaimer
Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.
Comments for this article