Quantcast
Channel: cyotek.com Blog Summary Feed
Viewing all articles
Browse latest Browse all 559

Painting animated images using C#

$
0
0

While reviewing The C# Top 100 it occurred to me that in my own code base I have many bits of code which may make useful blog posts, and that shouldn't take as long to write as the ones I usually create. Plus, I've a fair amount of source code for extending built in controls in various ways, creating new controls from scratch and other useful library code - I need to explore ways of decoupling some of that and releasing it for anyone to use.

To get started with this idea is a simple article on painting animated images using C#. If you assign an animated GIF file to the Image property of a Control, the .NET Framework will take care of animating the image for you. However, it only provides this automatically for the Image property and not for other properties such as BackgroundImage, or any custom image properties you add to your own components.

Fortunately the framework doesn't secret the animation functionality away and provides the static ImageAnimator class (located in System.Drawing) to handle the bulk of the work.

The demonstration program with an animated image

Click the above image to view the animated version. (Image Credit: Dominique Toussaint)

Checking if an image can be animated

The first thing to do is check if an animate can be animated. While calling the various ImageAnimator methods with static image (or even a null reference) won't crash, if your image is static then there's no need to call them in the first place.

The ImageAnimator.CanAnimate method takes a source Image and returns if it supports animation or not. Passing null to this method will also return false.

private Image _image;
private bool _isAnimating;

_image = LoadImageFromSomewhere();
_isAnimating = ImageAnimator.CanAnimate(_image);

The demonstration program with a static image

(Image Credit: Vera Kratochvil)

Preparing for animation

If your image supports animation, the next step is to call ImageAnimator.Animate, passing in both the source image and an EventHandler to receive change notifications.

This method will create a background thread that will periodically check watched images and advance frames as required. When it detects a new frame should be painted, it will call the event handler registered for the image, allowing you to handle the update, e.g. repaint your control.

Only one thread is created no matter how many images are being animated

private void SetupAnimation()
{
  _isAnimating = ImageAnimator.CanAnimate(_image);

  if (_isAnimating)
  {
    ImageAnimator.Animate(_image, this.OnFrameChangedHandler);
  }
}

private void OnFrameChangedHandler(object sender, EventArgs eventArgs)
{
  // trigger a repaint of our image
  customPaintPanel.Invalidate();
}

One mistake I sometimes see developers do is calling the Refresh method of a custom Windows Forms control. Calling Refresh will force the control and its children to be repainted immediately. An alternative way is to call Invalidate (without any arguments) which will mark the window to be repainted without forcing the paint or repainting child windows - generally this is more suitable and reduces the number of unneeded repaints.

Halting animation

When you are finished with the source image, you should call ImageAnimator.StopAnimate to remove the image and callback from the list of watched images.

private void CleanUp()
{
  if (_image != null)
  {
    // disable animations
    if (_isAnimating)
    {
      ImageAnimator.StopAnimate(_image, this.OnFrameChangedHandler);
    }

    _isAnimating = false;

    _image.Dispose();
    _image = null;
  }
}

Painting the image

The current frame is part of the Image instance's metadata, so you don't need to do anything specific to paint animated images vs static. With that said, the ImageAnimator class tracks the current frame separately and doesn't update the source Image until requested, with you do by calling ImageAnimator.UpdateFrames.

private void customPaintPanel_Paint(object sender, PaintEventArgs e)
{
  if (_isAnimating)
  {
    ImageAnimator.UpdateFrames(_image);
  }

  e.Graphics.DrawImage(_image, 0, 0);
}

Wrapping up

As you can probably see, this is quite a simple process and makes it easy to support animated graphics in applications that reference System.Drawing.

A complete example demonstrating how to use the ImageAnimator class is available from the link below.

Downloads

All content Copyright (c) by Cyotek Ltd or its respective writers. Permission to reproduce news and web log entries and other RSS feed content in unmodified form without notice is granted provided they are not used to endorse or promote any products or opinions (other than what was expressed by the author) and without taking them out of context. Written permission from the copyright owner must be obtained for everything else.
Original URL of this content is https://www.cyotek.com/blog/painting-animated-images-using-csharp?source=rss.


Viewing all articles
Browse latest Browse all 559

Trending Articles