4

I have a WinForms app that displays an animated gif in the simplest possible way - there is a PictureBox that loads the .gif directly.

The code generated by the WinForms designer looks like this:

        // 
        // pictureBoxHomer
        // 
        this.pictureBoxHomer.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
        this.pictureBoxHomer.Dock = System.Windows.Forms.DockStyle.Fill;
        this.pictureBoxHomer.Image = ((System.Drawing.Image)(resources.GetObject("pictureBoxHomer.Image")));
        this.pictureBoxHomer.Location = new System.Drawing.Point(3, 3);
        this.pictureBoxHomer.Name = "pictureBoxHomer";
        this.pictureBoxHomer.Size = new System.Drawing.Size(905, 321);
        this.pictureBoxHomer.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
        this.pictureBoxHomer.TabIndex = 0;
        this.pictureBoxHomer.TabStop = false;

The image is, of course, this: http://media.tumblr.com/tumblr_m1di1xvwTe1qz97bf.gif

Problem: while this animated gif displays wondrously in the browser, it is running way too fast in the WinForms app, which is not as happy as needed. So:

Question: is there a way to slow down an animated gif in a WinForms app?

Alvaro Rodriguez
  • 2,820
  • 2
  • 33
  • 38
  • 1
    The browser probably limits the gif to a specified FPS. Windows probably runs it as fast as the machine can process the next frame. – Stieffers Aug 20 '12 at 19:12
  • 1
    @Stieffers IIRC, the GIF format allows frame time to be specified in each frame. At least, some editors do. It seems odd that winforms would ignore that, but maybe it does? – ssube Aug 20 '12 at 19:27
  • 1
    I'm not sure of the intricacies of Winforms, but I highly doubt Winforms creates a new thread for every GIF image it loads, which would mean it renders the next frame as past as it can to avoid any hickups in the event delegation. – Stieffers Aug 20 '12 at 19:33

2 Answers2

4

I believe the answer is rather image-related than C#. If you edit that specific image in a tool like GIMP and take a look at the layers, you'll see it's a composition of 10 layers (frames) but no "delay time" between them is set - it has (0ms) in layer's attribute. You can edit layer's attribute and change it by right-clicking on it and selecting that option in menu. Of course, at the end you have to export your new image and save it as a GIF, selecting "animated" in options.

I believe in this case (when no delay time between frames is specified) web browser and C# PicutureBox force their own,different, default values. So, if you put a delay let say 100ms, like described here in step 3, you'll make the animation slow down.

mj82
  • 5,193
  • 7
  • 31
  • 39
  • 1
    Thank you, you've animated my afternoon - this worked perfectly. – Alvaro Rodriguez Aug 20 '12 at 20:36
  • 1
    If you have many frames, you can save yourself a lot of wrist pain by specifying the delay for all frames in the GIMP export step. The option is titled "Use delay entered above for all frames". – Lenna Nov 16 '12 at 19:08
  • 1
    my animated gif has delay time 30ms between all the frames(total 90 frames) is faster in IE but slow in winform picture box. Any idea why it is slow. I want it to be the same as it is in IE – hima Feb 03 '14 at 15:10
0

For future reference, it is possible to override the delay time of a GIF in a picture box. Here is a rough example:

    public partial class Form1 : Form
{
    private FrameDimension dimension;
    private int frameCount;
    private int indexToPaint;
    private Timer timer = new Timer();

    public Form1()
    {
        InitializeComponent();

        dimension = new FrameDimension(this.pictureBox1.Image.FrameDimensionsList[0]);
        frameCount = this.pictureBox1.Image.GetFrameCount(dimension);
        this.pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint); 
        timer.Interval = 100;
        timer.Tick += new EventHandler(timer_Tick);
        timer.Start();
    }

    void timer_Tick(object sender, EventArgs e)
    {
        indexToPaint++;
        if(indexToPaint >= frameCount)
        {
            indexToPaint = 0;
        }
    }

    void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        this.pictureBox1.Image.SelectActiveFrame(dimension, indexToPaint);
        e.Graphics.DrawImage(this.pictureBox1.Image, Point.Empty);
    }
}
Eric Dahlvang
  • 8,252
  • 4
  • 29
  • 50