Click here to Skip to main content
15,867,594 members
Articles / Desktop Programming / WPF

WPF GIF Animation

Rate me:
Please Sign up or sign in to vote.
4.89/5 (12 votes)
21 Apr 2010CPOL2 min read 96.9K   4.8K   31   15
This article shows the best way to play GIF animation in your WPF project.

Introduction

As I think many of us know, a standard set of WPF does not support animated GIF files. At the moment there are several approaches to solving this problem, but many of them have their own drawbacks - or take up a lot of CPU time, or take up a lot of resources. I designed and implemented its decision.

Background

My solution depends on working with System.Threading.Timer class, which helps me to organize succession of frames. But each frame has its own delay value. I decide to read it by parsing the GIF file with ParseGif class. So, the result is only consistent change frames, pre-freeze them in order to avoid memory leaks. More on how to prevent memory leaks, you can find in this remarkable article - Finding Memory Leaks in WPF-based applications.

Using the Code

Let's take a look.

Our solution is divided into two projects - a project of the class of animation, and project testing capabilities. I want to concentrate on the project testing. I did not add that there is one animation file - it would not display anything. I decided to add 100 smileys in the RichTextBox, which in this context, I think is the best option for demonstrating performance.

So, here is the main function LoadSmile of loading animation:

C#
private static void OnAnimatedBitmapChanged
    (DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            AnimatedImage control = (AnimatedImage)obj;

            control.UpdateAnimatedBitmap();

            RoutedPropertyChangedEventArgs<bitmap> e = 
		new RoutedPropertyChangedEventArgs<bitmap>(
                (Bitmap)args.OldValue, 
        (Bitmap)args.NewValue, AnimatedBitmapChangedEvent);
            control.OnAnimatedBitmapChanged(e);
        }

        public static readonly RoutedEvent AnimatedBitmapChangedEvent = 
        EventManager.RegisterRoutedEvent(
            "AnimatedBitmapChanged", RoutingStrategy.Bubble,
            typeof(RoutedPropertyChangedEventHandler<bitmap>), typeof(AnimatedImage));

...

        public void LoadSmile(Bitmap bitmap)
        {
            this.AnimatedBitmap = bitmap;
        }    

Then when you change the image, processing function is executed. In it, we are performing and disassembling GIF file and start the timer, which change the frames.

C#
private void UpdateAnimatedBitmap()
        {
            try
            {
                int nTimeFrames = GetFramesCount(); //get frames count
                _nCurrentFrame = 0; //Set current frame to default value
                if (nTimeFrames > 0) //this is animated file
                {
                    MemoryStream stream = new MemoryStream();
                    AnimatedBitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Gif);
                    stream.Seek(0, SeekOrigin.Begin);
                    byte[] buffer = new byte[stream.Length];
                    stream.Read(buffer, 0, buffer.Length);
                    ParseGif(buffer);
                    _BitmapSources = new List<bitmapsource>(nTimeFrames);
                    stream.Dispose();
                    FillBitmapSources(nTimeFrames);
                    timer = new Timer(OnFrameChanged, null, -1 , -1); //Initialize timer
                    StartAnimate(); //start animation
                }
                else //this is single image
                {
                    Bitmap bitmap = new Bitmap(AnimatedBitmap);
                    _BitmapSources = new List<bitmapsource>(1);
                    _BitmapSources.Add(CreateBitmapSourceFromBitmap(bitmap));
                    Source = _BitmapSources[0];
                }
            }
            catch { }
        }

In the attached project at the beginning of the article, you can find some of the functions carried out in this code. As you can see, the architecture of the decision is not very hard. We could use the built-in Windows Forms class ImageAnimator, but as practice for large-scale solutions in WPF, this class is poorly suited.

I think the most striking example of this model is the program for a chat. Often, it must be enforced at the same time tens of smiles. Naturally, this should not upload a lot of resources and CPU time for the comfort of the client.

Finally, I think of bringing the code in which there is a succession of frames.

C#
private void OnFrameChanged(object obj)
       {
           try
           {
               Dispatcher.BeginInvoke(DispatcherPriority.Render,
           new VoidDelegate(delegate { ChangeSource(); }));
           }
           catch { }
       }

       void ChangeSource()
       {
           try
           {
               timer.Change(Delays[_nCurrentFrame]
           * 10, 0); //get the current delay for the frame
               Source = _BitmapSources[_nCurrentFrame++]; //make it visible
               _nCurrentFrame = _nCurrentFrame %
           _BitmapSources.Count; //compute the next frame index
           }
           catch { }
       }

Also, our class implemented IDisposable interface which allows you to free resources when smile is unneeded:

C#
public void Dispose()
        {
            try
            {
                timer.Change(-1, -1);
                timer.Dispose();
                _BitmapSources.Clear();
                Source = null;
            }
            catch { }
        }

In principle, I think you will understand the main idea of this code.
In the attached file, you can find the rest of the code and a very easy project for testing.

Conclusion

In this article, I tried to describe the possibility of not displaying an animated file somehow, but to show the possibility of creating a code that can truly withstand high pressures and great economical resource, avoiding memory leaks.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionI can't download the source files Pin
SubmarineX31-Mar-14 17:12
SubmarineX31-Mar-14 17:12 
AnswerRe: I can't download the source files Pin
Artem S. Dmitriev4-Jun-14 6:08
Artem S. Dmitriev4-Jun-14 6:08 
GeneralMy vote of 4 Pin
Paul Paul.KernOneperiod@gmail.com14-Mar-13 3:06
Paul Paul.KernOneperiod@gmail.com14-Mar-13 3:06 
GeneralMy vote of 5 Pin
Dzung Le2-May-12 22:17
Dzung Le2-May-12 22:17 
QuestionWhy "ref"? Pin
gqqnbig19-Jan-12 21:34
gqqnbig19-Jan-12 21:34 
GeneralMy vote of 3 Pin
Mohammad Sadegh Shad1-Mar-11 10:34
Mohammad Sadegh Shad1-Mar-11 10:34 
QuestionHow to use it without the code behind Pin
theMpAmit2-Jan-11 20:46
theMpAmit2-Jan-11 20:46 
GeneralR Pin
mpggkobol18-May-10 9:42
mpggkobol18-May-10 9:42 
GeneralRe: R Pin
Artem S. Dmitriev4-Jun-10 8:51
Artem S. Dmitriev4-Jun-10 8:51 
QuestionGC.Collect??? Pin
Paulo Zemek16-Apr-10 11:14
mvaPaulo Zemek16-Apr-10 11:14 
AnswerRe: GC.Collect??? Pin
Artem S. Dmitriev17-Apr-10 3:04
Artem S. Dmitriev17-Apr-10 3:04 
GeneralTest App Missing Pin
sam.hill10-Apr-10 14:26
sam.hill10-Apr-10 14:26 
GeneralRe: Test App Missing Pin
Artem S. Dmitriev10-Apr-10 19:43
Artem S. Dmitriev10-Apr-10 19:43 
GeneralRe: Test App Missing Pin
sam.hill11-Apr-10 6:11
sam.hill11-Apr-10 6:11 
GeneralRe: Test App Missing Pin
Artem S. Dmitriev11-Apr-10 6:28
Artem S. Dmitriev11-Apr-10 6:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.