C#窗体上怎么显示动态图片如gif

2009年4月2日星期四

C#窗体上怎么显示动态图片如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


例子:摘自(http://www.cnblogs.com/cpw999cn/archive/2009/02/07/1385885.html)


最近在做一个图片查看器,由于使用一般的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. }
  57. }

0 评论:

发表评论