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 Fileds
        private FileInfo fileInfo;
        private IList<Image> frames;
        private Size size;
        private bool animated;
        private bool loop;
        private TimeSpan animationDuration;
        #endregion

        #region Properties
        public 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

Sample

 

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-0.gif
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

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.


About the author

DEJAN STOJANOVIC

Dejan Stojanovic is a passionate Software Architect/Developer. He is highly experienced in .NET programming platform includion ASP.NET MVC and WebApi. He likes working on new technologies and exciting challenging projects

CONNECT WITH DEJAN  Loginlinkedin Logintwitter Logingoogleplus Logingoogleplus

JavaScript

read more

SQL/T-SQL

read more

Umbraco CMS

read more

PowerShell

read more

Comments for this article