1. 程式人生 > >c# winform 顯示動態gif圖片的方法

c# winform 顯示動態gif圖片的方法

方法一(簡單):用label,然後設定為背景圖片

方法二:使用GDI+ 來實現 (很粗略的實現,沒有幀間隔)

          Image image = Image.FromFile("e://temp.gif");

            FrameDimension fd = new FrameDimension(image.FrameDimensionsList[0]);

            int count = image.GetFrameCount(fd);

            Graphics g = this.panel1.CreateGraphics();

            while (true) {
                 for (int i = 0; i < count; i++){
                    //g.Clear(Color.White); 
                   image.SelectActiveFrame(fd, i);
                    g.DrawImage(image, new Point(0, 0));
                    System.Threading.Thread.Sleep(100);
                    Application.DoEvents();
                }
            }

方法三:(推薦)

Bitmap animatedGif = new Bitmap("e://temp2.gif");
            Graphics g = this.panel1.CreateGraphics();
            // A Gif image's frame delays are contained in a byte array
            // in the image's PropertyTagFrameDelay Property Item's
            // value property.
            // Retrieve the byte array...
            int PropertyTagFrameDelay = 0x5100;
            PropertyItem propItem = animatedGif.GetPropertyItem(PropertyTagFrameDelay);
            byte[] bytes = propItem.Value;
            // Get the frame count for the Gif...
            FrameDimension frameDimension = new FrameDimension(animatedGif.FrameDimensionsList[0]);
            int frameCount = animatedGif.GetFrameCount(FrameDimension.Time);
            // Create an array of integers to contain the delays,
            // in hundredths of a second, between each frame in the Gif image.
            int[] delays = new int[frameCount + 1];
            int i = 0;
            for (i = 0; i <= frameCount - 1; i++)
            {
                delays[i] = BitConverter.ToInt32(bytes, i * 4);
            }

            // Play the Gif one time...
            while (true)
            {
                for (i = 0; i <= animatedGif.GetFrameCount(frameDimension) - 1; i++)
                {
                    animatedGif.SelectActiveFrame(frameDimension, i);
                    g.DrawImage(animatedGif, new Point(0, 0));
                    Application.DoEvents();
                    Thread.Sleep(delays[i] * 10);
                }
            }

方法四: 使用.NET 自帶的類:System.Drawing.ImageAnimator

最近在做一個圖片檢視器,由於使用一般的PctureBox,在效能和縮放控制上都無法滿足預期的要求,因此所有元件的呈現均是通過重寫控制元件的OnPaint事件來繪製。在檢視gif圖片時發現Graphics.DrawImage只呈現第一幀,無法滿足預期要求,因此經過摸索尋找到了解決自繪gif的較好辦法。

這裡介紹一個.net自身攜帶的類ImageAnimator,這個類類似於控制動畫的時間軸,使用ImageAnimator.CanAnimate可以判斷一個圖片是否為動畫,呼叫ImageAnimator.Animate可以開始播放動畫,即每經過一幀的時間觸發一次OnFrameChanged委託,我們只要在該委託中將Image的活動幀選至下一幀再迫使介面重繪就可以實現動畫效果了。

為了方便以後的使用,我將這些程式碼整合到了一起,形成一個AnimateImage類,該類提供了CanAnimate、FrameCount、CurrentFrame等屬性,以及Play()、Stop()、Reset()等動畫常用的方法,程式碼如下

  1. using System;      
  2. using System.Collections.Generic;      
  3. using System.Text;      
  4. using System.Drawing;      
  5. using System.Drawing.Imaging;      
  6. namespace GifTest      
  7. {      
  8.     /**//// <summary>      
  9.   /// 表示一類帶動畫功能的影象。      
  10.   /// </summary>      
  11.   public class AnimateImage      
  12.    {      
  13.        Image image;      
  14.        FrameDimension frameDimension;      
  15.       /**//// <summary>      
  16.       /// 動畫當前幀發生改變時觸發。      
  17.       /// </summary>      
  18.       public event EventHandler<EventArgs> OnFrameChanged;      
  19.      /**//// <summary>      
  20.       /// 例項化一個AnimateImage。      
  21.       /// </summary>      
  22.       /// <param name="img">動畫圖片。</param>      
  23.       public AnimateImage(Image img)      
  24.        {      
  25.            image = img;      
  26.           lock (image)      
  27.           {      
  28.                mCanAnimate = ImageAnimator.CanAnimate(image);      
  29.               if (mCanAnimate)      
  30.                {      
  31.                   Guid[] guid = image.FrameDimensionsList;      
  32.                    mFrameCount = image.GetFrameCount(frameDimension);      
  33.                }      
  34.            }      
  35.        }      
  36.      bool mCanAnimate;      
  37.      int mFrameCount = 1, mCurrentFrame = 0;      
  38.       /**//// <summary>      
  39.      /// 圖片。      
  40.       /// </summary>      
  41.       public Image Image      
  42.        {      
  43.           get { return image; }      
  44.        }      
  45.       /**//// <summary>      
  46.       /// 是否動畫。      
  47.      /// </summary>      
  48.       public bool CanAnimate      
  49.        {      
  50.           get { return mCanAnimate; }      
  51.       }      
  52.        /**//// <summary>      
  53.     /// 總幀數。      
  54.       /// </summary>      
  55.       public int FrameCount      
  56.        {      
  57.            get { return mFrameCount; }      
  58.         }      
  59.        /**//// <summary>      
  60.        /// 播放的當前幀。      
  61.        /// </summary>      
  62.        public int CurrentFrame      
  63.         {      
  64.            get { return mCurrentFrame; }      
  65.         }        
  66.        /**//// <summary>      
  67.       /// 播放這個動畫。      
  68.       /// </summary>      
  69.        public void Play()      
  70.        {      
  71.           if (mCanAnimate)      
  72.            {      
  73.               lock (image)      
  74.                {      
  75.                    ImageAnimator.Animate(image, new EventHandler(FrameChanged));      
  76.                }      
  77.            }      
  78.        }      
  79.       /**//// <summary>      
  80.       /// 停止播放。      
  81.       /// </summary>      
  82.       public void Stop()      
  83.        {      
  84.           if (mCanAnimate)      
  85.            {      
  86.               lock (image)      
  87.                {      
  88.                    ImageAnimator.StopAnimate(image, new EventHandler(FrameChanged));      
  89.                }      
  90.            }      
  91.        }      
  92.       /**//// <summary>      
  93.       /// 重置動畫,使之停止在第0幀位置上。      
  94.       /// </summary>      
  95.       public void Reset()      
  96.        {      
  97.           if (mCanAnimate)      
  98.            {      
  99.                ImageAnimator.StopAnimate(image, new EventHandler(FrameChanged));      
  100.               lock (image)      
  101.                {      
  102.                    image.SelectActiveFrame(frameDimension, 0);      
  103.                    mCurrentFrame = 0;      
  104.                }      
  105.            }      
  106.        }      
  107.       private void FrameChanged(object sender, EventArgs e)      
  108.        {      
  109.            mCurrentFrame = mCurrentFrame + 1 >= mFrameCount ? 0 : mCurrentFrame + 1;      
  110.           lock (image)      
  111.            {      
  112.                image.SelectActiveFrame(frameDimension, mCurrentFrame);      
  113.            }      
  114.           if (OnFrameChanged != null)      
  115.            {      
  116.                OnFrameChanged(image, e);      
  117.            }      
  118.        }      
  119.    }      

使用如下方法呼叫:

  1. using System;      
  2. using System.Collections.Generic;      
  3. using System.ComponentModel;      
  4. using System.Data;      
  5. using System.Drawing;      
  6. using System.Drawing.Imaging;      
  7. using System.Text;      
  8. using System.Windows.Forms;      
  9. namespace GifTest      
  10. {      
  11.     public partial class Form1 : Form      
  12.      {      
  13.          AnimateImage image;      
  14.         public Form1()      
  15.          {      
  16.              InitializeComponent();      
  17.              image = new AnimateImage(Image.FromFile(@"C:/Documents and Settings/Administrator/My Documents/My Pictures/未命名.gif"));      
  18.              image.OnFrameChanged += new EventHandler<EventArgs>(image_OnFrameChanged);      
  19.              SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);      
  20.          }      
  21.         void image_OnFrameChanged(object sender, EventArgs e)      
  22.          {      
  23.              Invalidate();      
  24.          }      
  25.         private void Form1_Load(object sender, EventArgs e)      
  26.          {      
  27.              image.Play();      
  28.          }      
  29.         private void Form1_Paint(object sender, PaintEventArgs e)      
  30.          {      
  31.             lock (image.Image)      
  32.              {      
  33.                  e.Graphics.DrawImage(image.Image, new Point(0, 0));      
  34.              }      
  35.          }      
  36.         private void button1_Click(object sender, EventArgs e)      
  37.          {      
  38.             if (button1.Text.Equals("Stop"))      
  39.              {      
  40.                  image.Stop();      
  41.                  button1.Text = "Play";      
  42.              }      
  43.             else     
  44.              {      
  45.                  image.Play();      
  46.                  button1.Text = "Stop";      
  47.              }      
  48.              Invalidate();      
  49.          }      
  50.         private void button2_Click(object sender, EventArgs e)      
  51.          {      
  52.              image.Reset();      
  53.              button1.Text = "Play";      
  54.              Invalidate();      
  55.          }      
  56.      }