Click here to Skip to main content
Click here to Skip to main content
Go to top

WPF GIF Animation

, 21 Apr 2010
Rate this:
Please Sign up or sign in to vote.
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:

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.

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.

 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:

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)

Share

About the Author

Artem S. Dmitriev
Software Developer
Russian Federation Russian Federation
No Biography provided

Comments and Discussions

 
AnswerRe: GC.Collect??? Pinmembermartyn_mcfly17-Apr-10 3:04 
GeneralTest App Missing Pinmembersam.hill10-Apr-10 14:26 
GeneralRe: Test App Missing Pinmembermartyn_mcfly10-Apr-10 19:43 
GeneralRe: Test App Missing Pinmembersam.hill11-Apr-10 6:11 
GeneralRe: Test App Missing Pinmembermartyn_mcfly11-Apr-10 6:28 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 21 Apr 2010
Article Copyright 2010 by Artem S. Dmitriev
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid