c# winform 顯示動態gif圖片的方法
阿新 • • 發佈:2019-01-31
方法一(簡單):用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()等動畫常用的方法,程式碼如下
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Drawing;
- using System.Drawing.Imaging;
- namespace GifTest
- {
- /**//// <summary>
- /// 表示一類帶動畫功能的影象。
- /// </summary>
- public class AnimateImage
- {
- Image image;
- FrameDimension frameDimension;
- /**//// <summary>
- /// 動畫當前幀發生改變時觸發。
- /// </summary>
- public event EventHandler<EventArgs> OnFrameChanged;
- /**//// <summary>
- /// 例項化一個AnimateImage。
- /// </summary>
- /// <param name="img">動畫圖片。</param>
- public AnimateImage(Image img)
- {
- image = img;
- lock (image)
- {
- mCanAnimate = ImageAnimator.CanAnimate(image);
- if (mCanAnimate)
- {
- Guid[] guid = image.FrameDimensionsList;
- mFrameCount = image.GetFrameCount(frameDimension);
- }
- }
- }
- bool mCanAnimate;
- int mFrameCount = 1, mCurrentFrame = 0;
- /**//// <summary>
- /// 圖片。
- /// </summary>
- public Image Image
- {
- get { return image; }
- }
- /**//// <summary>
- /// 是否動畫。
- /// </summary>
- public bool CanAnimate
- {
- get { return mCanAnimate; }
- }
- /**//// <summary>
- /// 總幀數。
- /// </summary>
- public int FrameCount
- {
- get { return mFrameCount; }
- }
- /**//// <summary>
- /// 播放的當前幀。
- /// </summary>
- public int CurrentFrame
- {
- get { return mCurrentFrame; }
- }
- /**//// <summary>
- /// 播放這個動畫。
- /// </summary>
- public void Play()
- {
- if (mCanAnimate)
- {
- lock (image)
- {
- ImageAnimator.Animate(image, new EventHandler(FrameChanged));
- }
- }
- }
- /**//// <summary>
- /// 停止播放。
- /// </summary>
- public void Stop()
- {
- if (mCanAnimate)
- {
- lock (image)
- {
- ImageAnimator.StopAnimate(image, new EventHandler(FrameChanged));
- }
- }
- }
- /**//// <summary>
- /// 重置動畫,使之停止在第0幀位置上。
- /// </summary>
- public void Reset()
- {
- if (mCanAnimate)
- {
- ImageAnimator.StopAnimate(image, new EventHandler(FrameChanged));
- lock (image)
- {
- image.SelectActiveFrame(frameDimension, 0);
- mCurrentFrame = 0;
- }
- }
- }
- private void FrameChanged(object sender, EventArgs e)
- {
- mCurrentFrame = mCurrentFrame + 1 >= mFrameCount ? 0 : mCurrentFrame + 1;
- lock (image)
- {
- image.SelectActiveFrame(frameDimension, mCurrentFrame);
- }
- if (OnFrameChanged != null)
- {
- OnFrameChanged(image, e);
- }
- }
- }
使用如下方法呼叫:
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Text;
- using System.Windows.Forms;
- namespace GifTest
- {
- public partial class Form1 : Form
- {
- AnimateImage image;
- public Form1()
- {
- InitializeComponent();
- image = new AnimateImage(Image.FromFile(@"C:/Documents and Settings/Administrator/My Documents/My Pictures/未命名.gif"));
- image.OnFrameChanged += new EventHandler<EventArgs>(image_OnFrameChanged);
- SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
- }
- void image_OnFrameChanged(object sender, EventArgs e)
- {
- Invalidate();
- }
- private void Form1_Load(object sender, EventArgs e)
- {
- image.Play();
- }
- private void Form1_Paint(object sender, PaintEventArgs e)
- {
- lock (image.Image)
- {
- e.Graphics.DrawImage(image.Image, new Point(0, 0));
- }
- }
- private void button1_Click(object sender, EventArgs e)
- {
- if (button1.Text.Equals("Stop"))
- {
- image.Stop();
- button1.Text = "Play";
- }
- else
- {
- image.Play();
- button1.Text = "Stop";
- }
- Invalidate();
- }
- private void button2_Click(object sender, EventArgs e)
- {
- image.Reset();
- button1.Text = "Play";
- Invalidate();
- }
- }
- }