GIF animation CPU consumption problem in C#!

Refresh

April 2019

Views

940 time

1

I have made a GIF Animation user control which loads gif animations and have created about 30 of them in my project each animating a GIF. The problem is that when I check my CPU usage it is about 70%+!!! I'm sure something is wrong with this! Please help me. Here is the code of that GIF Animator control:

public class AnimatedImage : System.Windows.Controls.Image
{
    private BitmapSource[] _BitmapSources = null;
    private int _nCurrentFrame=0;


    private bool _bIsAnimating=false;

    public bool IsAnimating
    {
        get { return _bIsAnimating; }
    }

    static AnimatedImage()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(AnimatedImage), new FrameworkPropertyMetadata(typeof(AnimatedImage)));
    }
    public Bitmap AnimatedBitmap
    {
        get { return (Bitmap)GetValue(AnimatedBitmapProperty); }
        set { StopAnimate(); SetValue(AnimatedBitmapProperty, value); }
    }

    /// <summary>
    /// Identifies the Value dependency property.
    /// </summary>
    public static readonly DependencyProperty AnimatedBitmapProperty =
        DependencyProperty.Register(
            "AnimatedBitmap", typeof(Bitmap), typeof(AnimatedImage),
            new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnAnimatedBitmapChanged)));

    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);
    }

    /// <summary>
    /// Identifies the ValueChanged routed event.
    /// </summary>
    public static readonly RoutedEvent AnimatedBitmapChangedEvent = EventManager.RegisterRoutedEvent(
        "AnimatedBitmapChanged", RoutingStrategy.Bubble,
        typeof(RoutedPropertyChangedEventHandler<Bitmap>), typeof(AnimatedImage));

    /// <summary>
    /// Occurs when the Value property changes.
    /// </summary>
    public event RoutedPropertyChangedEventHandler<Bitmap> AnimatedBitmapChanged
    {
        add { AddHandler(AnimatedBitmapChangedEvent, value); }
        remove { RemoveHandler(AnimatedBitmapChangedEvent, value); }
    }

     /// <summary>
     /// Raises the ValueChanged event.
     /// </summary>
    /// <param name="args">Arguments associated with the ValueChanged event.</param>
    protected virtual void OnAnimatedBitmapChanged(RoutedPropertyChangedEventArgs<Bitmap> args)
    {
        RaiseEvent(args);
      }
    private void UpdateAnimatedBitmap()
    {                       
        int nTimeFrames = AnimatedBitmap.GetFrameCount(System.Drawing.Imaging.FrameDimension.Time);
        _nCurrentFrame = 0;
        if (nTimeFrames > 0)
        {

            _BitmapSources = new BitmapSource[nTimeFrames];

            for (int i = 0; i < nTimeFrames; i++)
            {

                AnimatedBitmap.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Time, i);
                Bitmap bitmap = new Bitmap(AnimatedBitmap);
                bitmap.MakeTransparent();

                _BitmapSources[i] = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    bitmap.GetHbitmap(),
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
            }
            StartAnimate();
        }
    }
    private delegate void VoidDelegate();

    private void OnFrameChanged(object o, EventArgs e)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Render, new VoidDelegate(delegate { ChangeSource(); }));

    }
    void ChangeSource()
    {            
        Source = _BitmapSources[_nCurrentFrame++];
        _nCurrentFrame = _nCurrentFrame % _BitmapSources.Length;
        ImageAnimator.UpdateFrames();

    }

    public void StopAnimate()
    {
        if (_bIsAnimating)
        {
             ImageAnimator.StopAnimate(AnimatedBitmap, new EventHandler(this.OnFrameChanged));
            _bIsAnimating = false;
        }
    }

    public void StartAnimate()
    {
        if (!_bIsAnimating)
        {

            ImageAnimator.Animate(AnimatedBitmap, new EventHandler(this.OnFrameChanged));
            _bIsAnimating = true;
        }
    }

}

}

Moh

1 answers

1

Give this one a shot. We've used it in our application and I haven't notice any weird memory consumption.