none
How to use an animated gif?

    Question

  • I was wondering if there was a way to play an animated gif?  I tried setting the source of an image to a gif file but it only loads the first frame of the gif and that's it.
    Tuesday, March 28, 2006 12:04 AM

Answers

  • Another really simple workaround is to use MediaElement, and set the source of the MediaElement to the gif file.

        <MediaElement Source="animated.gif"/>

     

    -Thanks

    Rahul Patil

    Tuesday, March 28, 2006 6:27 PM
  • Unfortunately for V1, we have not automatic way of animating a GIF. This is something we are looking at fixing for the next version.

    One workaround would be animate the different frames manually.

    Tuesday, March 28, 2006 6:39 AM

All replies

  • Unfortunately for V1, we have not automatic way of animating a GIF. This is something we are looking at fixing for the next version.

    One workaround would be animate the different frames manually.

    Tuesday, March 28, 2006 6:39 AM
  • Hm, ok.  Do you have any suggestions on how I can go about animating manually?
    Tuesday, March 28, 2006 4:54 PM
  • Another really simple workaround is to use MediaElement, and set the source of the MediaElement to the gif file.

        <MediaElement Source="animated.gif"/>

     

    -Thanks

    Rahul Patil

    Tuesday, March 28, 2006 6:27 PM
  • Have anyone tried this?

    It seems mediaElement won't show animated gif either.

    this is my code.

    <MediaElement x:Name="loadingGif" Width="50" Height="100" Source="pack://siteoforigin:,,,/images/loading.gif" HorizontalAlignment="Center"></MediaElement>

    thanks/chong

    Wednesday, March 29, 2006 10:09 PM
  • The MediaElement doesn't support the pack:// scheme yet. Try a relative or absolute URI such as http:// or file://. It downloads and plays the GIF just fine.

    Wednesday, March 29, 2006 10:51 PM
  • For some reason I still cannot get this to work :(.

    Here is all I am doing:

    <MediaElement Source="animation.gif">

    I have the animation.gif as an item in my project.  When I load up my Window however, I just see a blank space.  The link is correct because if I switch MediaElement with Image I see the first frame of my gif.

    Saturday, April 01, 2006 12:01 AM
  • That relative path is shorthand for "pack://application:,,,/animation.gif" which doesn't work. The best way to refer to media today is to use an absolute URI to a loose file outside of the project.
    Saturday, April 01, 2006 12:12 AM
  • I'm using a MediaElement to animate a GIF successfully, in this way:

    <MediaElement LoadedBehavior="Play" Source="file://C:/anim.gif" />

    However, when the GIF has transparency, the MediaElement shows black in the areas that should be transparent...ostensibly, the transparent areas of the GIF would show the underlying control.  How can I change this?

    Also, I don't really like the idea of using a MediaElement for the task of animating small GIFs, such as animating emoticons for use in an IM application.  I feel that it's way too heavy an object to create and destroy frequently.  Does anyone have details on the frame-by-frame animation method?

    Sunday, April 02, 2006 4:31 AM
  • This article shows you how to enumerate through each frame in the animated gif file and obtain them as System.Drawing.Bitmap instances:

    http://www.eggheadcafe.com/articles/stripimagefromanimatedgif.asp

    This thread shows how to convert a System.Drawing.Bitmap into a BitmapSource, which can be displayed in the WPF Image control:

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=320846&SiteID=1

    I would think you could leverage this to create a user control based on the WPF Image control and a timer. The only thing I'm not sure of is how to determine how long you should pause between each frame. That information is of course stored in the gif file, but I'm not sure if you can obtain it through .Net.

    Unfortunately, I don't really have an idea how slow this would be. I'd venture to guess that the conversion of a Drawing.Bitmap to BitmapSource is a fairly costly process. You would probably want to convert all frames of the gif to BitmapSources as you load the gif file, and then cache them so you don't have to convert on each frame draw.

    Hope that helps...

    Jared

    Sunday, April 02, 2006 5:09 PM
  • Has the support for animated GIFs using Image been provided in the latest versions of WPF?
    Monday, October 23, 2006 10:50 AM
  • I'd also like to use animated GIFs.
    I tried:
    <Grid>
            <MediaElement Source="D:\Animation.gif" />
    </Grid>
    However, my Window is blank. I also tried to use Width and Height properties, but that didn't solve my problem.
    Tuesday, November 28, 2006 9:07 PM
  • Image element does not support Animated GIFs in this version. Some people have had luck using the MediaElement for Animated GIFs, but no guarantee is made about this solution.
    Thursday, November 30, 2006 5:17 PM
    Moderator
  • As a learning project I created a WPF control to display animated GIF files.  The "ImageAnim" control mimics most of the behavior of Microsoft's WPF "Image" control with the additional benefit of handling animated GIF's.  You can download ImageAnim.dll from www.robreiss.com. (its free)

    Rob Reiss

    Monday, March 26, 2007 9:31 PM
  • Hi All,

    For me giving file:// source to mediaelement is also not working.so i opted for http as follows


    Code Snippet
        <MediaElement Source="http://192.168.2.41/it/spinner_48.gif" x:Name="me" LoadedBehavior="Play" ToolTip="Loading..." Canvas.Top="50" UnloadedBehavior="Play" MediaFailed="me_MediaFailed"></MediaElement>
            <TextBlock x:Name="txtError"></TextBlock>

           

     

    but strange thing is it works in IE7 and fails in IE6. for IE6 it raises Mediafailed event and the exception is

    Code Snippet

    "media failed. system.windows.media.invalidwmpversionexception:Windows media player 10 or later is required--->system.runtime.interopservices.comexception(0x88989507).Exception from HRESULT(0x88989507)

    -------------------End of innerexception stack trace-------------------------"

     

     

    Above exception is caught in mediafailed event as follows:

     

    Code Snippet

    private void me_MediaFailed(object sender, ExceptionRoutedEventArgs e)
            {

                txtError.Text = "media failed " + e.ErrorException.ToString();
            }

     

     

    I agree that my client machine has windows media player 9 but how can need of WMP 10 be justified for a simple animated gif? How can i ask my client to take ie7 not ie6 and WMP 10 not 9 just for RICH UX web site(mostly containing animated gif) without video ?It really is going to embrace me

     

     

    Monday, May 12, 2008 12:21 PM

  • There is a better and easier way to animate a GIF. try using winforms PictureBox with the WindowsFormsHost element.
    The code will looks like

    <Window x:Class="Wing.TeleGYM.Client.Controls.StartupScreen"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wfi="clr-namespaceTongue Tiedystem.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
        xmlns:winForms="clr-namespaceTongue Tiedystem.Windows.Forms;assembly=System.Windows.Forms"
        Loaded="Window_Loaded" >

                <DockPanel ... >
                   
                    <wfi:WindowsFormsHost HorizontalAlignment="Center">
                        <winFormsStick out tongueictureBox x:Name="pictureBoxLoading" Width="320" Height="20" ></winFormsStick out tongueictureBox>
                    </wfi:WindowsFormsHost>
                </DockPanel >

    </Window >

    In the Window_Loaded function add the following line of code

    pictureBoxLoading.Image = Properties.Resources.StartUp_Loading; // From resources

    or

    pictureBoxLoading.Image = c:\loading.gif // from dis

    hope this will help
    Monday, May 19, 2008 2:39 PM
  • To solve the problem with playing animated GIFs I have created control derived from System.Windows.Controls.Image. This control uses System.Drawing.ImageAnimator class for animating GIF. The main functionality of class is the following:

    using System;
    using System.Drawing;
    using System.Windows;
    using System.Windows.Interop;
    using System.Windows.Threading;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using IpmPlayerLogWriter;

    public class GIFImageControl : System.Windows.Controls.Image
    {
        delegate void OnFrameChangedDelegate();  
        private Bitmap _Bitmap;

        public AnimatedImageControl(string path)
        {
                _Bitmap = (Bitmap)Bitmap.FromFile(path);
                ImageAnimator.Animate(_Bitmap, new EventHandler(OnFrameChanged));
        }


        private void OnFrameChanged(object sender, EventArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                new OnFrameChangedDelegate(OnFrameChangedInMainThread));
        }

        private void OnFrameChangedInMainThread()
        {
            ImageAnimator.UpdateFrames(_Bitmap);
            this.Source = this.GetBitmapSource(_Bitmap);
            InvalidateVisual();
        }

        private BitmapSource GetBitmapSource(Bitmap gdiBitmap)
        {
            return Imaging.CreateBitmapSourceFromHBitmap(
                gdiBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
        }
    }

    Hope that it helps :)
    Wednesday, June 04, 2008 6:03 AM
  • I have found one problem in the code I have posted above. Method GetBitmapSource gives memory leak and then GDI crashes. It is better be changed that way:

        [DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
        public static extern IntPtr DeleteObject(IntPtr hDc);

        private BitmapSource GetBitmapSource(Bitmap gdiBitmap)
        {
                IntPtr hBitmap = gdiBitmap.GetHbitmap();
                bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(hBitmap,
                                                                     IntPtr.Zero,
                                                                     Int32Rect.Empty,
                                                                     BitmapSizeOptions.FromEmptyOptions());
                DeleteObject(hBitmap);
        }


    Wednesday, June 04, 2008 7:18 AM
  • This thread is great.  I used Sergey Ukraine's info here and made a downloadable control that will display animated .gif from either the filesystem, or from an embedded resource in the assembly.  Additionally, I added the functionality to Play/Pause the animation by clicking on the .gif.  (On by default, but can be turned off with AllowClickToPause to false.)

    I posted the code on my blog, where the whole downloadable project can be downloaded.


    The Pragmatic TSQL Programmer
    Friday, March 20, 2009 10:06 PM
  • Hi

    I had the same problem, so I created a new control, deriving it from the Image class, and applying an animation to the image with a dependency property called FrameIndex. I guess that the frame rate is 10 frames per second.

    This control works well when you are adding the control manually to a container. Some modifications are be required to use it from XAML (using a parameterless constructor).

    The control accepts any URI (I tried with packed URIs) in the constructor.

    class GifImage : Image {

        public int FrameIndex {
            get { return (int)GetValue(FrameIndexProperty); }
            set { SetValue(FrameIndexProperty, value); }
        }

        public static readonly DependencyProperty FrameIndexProperty =
            DependencyProperty.Register("FrameIndex", typeof(int), typeof(GifImage), new UIPropertyMetadata(0, new PropertyChangedCallback(ChangingFrameIndex)));

        static void ChangingFrameIndex(DependencyObject obj, DependencyPropertyChangedEventArgs ev) {
            GifImage ob = obj as GifImage;
            ob.Source = ob.gf.Frames[(int)ev.NewValue];
            ob.InvalidateVisual();
        }
        GifBitmapDecoder gf;
        Int32Animation anim ;           
        public GifImage(Uri uri) {
            gf = new GifBitmapDecoder(uri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            anim = new Int32Animation(0, gf.Frames.Count - 1, new Duration(new TimeSpan(0,0, 0,gf.Frames.Count/10,(int)((gf.Frames.Count/10.0-gf.Frames.Count/10)*1000))));
            anim.RepeatBehavior = RepeatBehavior.Forever;
            Source = gf.Frames[0];
        }
        bool animationIsWorking = false;
        protected override void OnRender(DrawingContext dc) {
            base.OnRender(dc);
            if (!animationIsWorking) {
                BeginAnimation(FrameIndexProperty, anim);
                animationIsWorking = true;
            }
        }
    }

    • Proposed as answer by ptkdb Thursday, August 20, 2009 2:05 PM
    Friday, July 17, 2009 2:02 PM
  • Works nicely...   Thanks for this. 

       Had some very marginal success using a MediaElement but the playback was horrid and drilling through the myriad of properties, clocks, storyboards, triggers, speedratios, repeatbehavior was getting more and more frustrating just to animate a 16x16 icon.

      I think this is about as straightforward as is possible for a simple animation in WPF. 

    Only tweek I had to make was to apply "Stretch=Stretch.None" to keep the image at its original size when I used it as content in a button.

    • Edited by ptkdb Thursday, August 20, 2009 2:05 PM felt it needed embellishment
    Thursday, August 20, 2009 1:59 PM
  • Jesus,

    I like your approach since it doesn't require the image format to be retranslated from an HBitmap for every frame display the way Sergey and Greg's did.  I implemented a variation that can be used from XAML and that hides a little more of the implementation from the caller (by not having an exposed FrameIndex property).  I no habla C# so my version is in VB:

    Imports System.Drawing
    Imports System.Threading
    Imports Image = System.Windows.Controls.Image
    
    Public Class AnimatedGIFViewer
        Inherits Image
    
        Private _GIFDecoder As GifBitmapDecoder
        Private _FrameTimer As Timer
        Private _ShowingFrame As Boolean = False
        Private _FrameIndex As Integer
    
        Public Property GIFSource() As Uri
            Get
                Return DirectCast(GetValue(GIFSourceProperty), Uri)
            End Get
    
            Set(ByVal value As Uri)
                SetValue(GIFSourceProperty, value)
            End Set
        End Property
    
        Public Shared ReadOnly GIFSourceProperty As DependencyProperty = _
            DependencyProperty.Register( _
                "GIFSource" _
                , GetType(Uri) _
                , GetType(AnimatedGIFViewer) _
                , New FrameworkPropertyMetadata(Nothing, AddressOf GIFSource_Changed) _
            )
    
        Private Shared Sub GIFSource_Changed(ByVal sender As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
            DirectCast(sender, AnimatedGIFViewer).GIFSourceSet()
        End Sub
    
        Private Sub GIFSourceSet()
            KillCurrentTimer()
    
            If IsNothing(GIFSource) Then
                _GIFDecoder = Nothing
            Else
                _GIFDecoder = New GifBitmapDecoder(GIFSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default)
                _FrameIndex = 0
                _FrameTimer = New Timer(AddressOf ShowFrame, Nothing, 200, 200)
            End If
        End Sub
    
        Private Sub ShowFrame(ByVal State As Object)
    
            'Avoid getting flooded 
            'with event calls since
            'the timer doesn't pay
            'any attention to whether
            'we are keeping up or not.
            If _ShowingFrame Then
                Exit Sub
            End If
    
            _ShowingFrame = True
            Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, New Action(AddressOf OnFrameChanged))
            _ShowingFrame = False
        End Sub
    
        Private Sub OnFrameChanged()
            Source = _GIFDecoder.Frames(_FrameIndex)
            _FrameIndex += 1
    
            If (_FrameIndex = _GIFDecoder.Frames.Count) Then
                _FrameIndex = 0
            End If
    
        End Sub
    
        Private Sub KillCurrentTimer()
    
            If (Not IsNothing(_FrameTimer)) Then
                Dim FrameTimerDisposed As New AutoResetEvent(False)
                _FrameTimer.Dispose(FrameTimerDisposed)
                'In order to ensure that we don't have
                'two timers going at once, we will wait
                'for the dispose to complete but only 
                'for up to 1 second.
                FrameTimerDisposed.WaitOne(1000)
                _ShowingFrame = False
                _FrameTimer = Nothing
            End If
    
        End Sub
    
        Private Sub AnimatedGIFViewer_Unloaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Unloaded
            KillCurrentTimer()
        End Sub
    
    End Class
    

    You can use it XAML as follows:

            <local:AnimatedGIFViewer 
                Height="130" 
                Width="156" 
                x:Name="Image1" 
                Stretch="None" 
    GIFSource="pack://application:,,,/MyProject;component/MyGif.gif"
             />
    


    -JLS
    Wednesday, September 09, 2009 1:03 PM
  • Thanks, this solution works fine, but how is possible that microsoft don't fix mediaElement control problem !?
    Monday, September 21, 2009 3:44 PM
  • I would really hope Microsoft supports animated GIF directly in Image
    Tuesday, October 13, 2009 4:06 PM
  • You should try this article.
    Sunday, April 11, 2010 6:54 AM