public void Bitmap CreateAnimation(Bitmap[] frames, int[] delays)
对于预期实现设置严格限制并不明智。从技术上讲,利用TIFF图像格式是可以实现的,它能够存储多个帧。但是它们不是基于时间的,只有GIF编解码器支持这一点。需要提供一个额外的参数,以便在下一张图片需要呈现时更新控件。就像这样:
public static Image CreateAnimation(Control ctl, Image[] frames, int[] delays) {
var ms = new System.IO.MemoryStream();
var codec = ImageCodecInfo.GetImageEncoders().First(i => i.MimeType == "image/tiff");
EncoderParameters encoderParameters = new EncoderParameters(2);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.MultiFrame);
encoderParameters.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)EncoderValue.CompressionLZW);
frames[0].Save(ms, codec, encoderParameters);
encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.FrameDimensionPage);
for (int i = 1; i < frames.Length; i++) {
frames[0].SaveAdd(frames[i], encoderParameters);
}
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.Flush);
frames[0].SaveAdd(encoderParameters);
ms.Position = 0;
var img = Image.FromStream(ms);
Animate(ctl, img, delays);
return img;
}
Animate()方法需要一个定时器来选择下一帧并更新控件:
private static void Animate(Control ctl, Image img, int[] delays) {
int frame = 0;
var tmr = new Timer() { Interval = delays[0], Enabled = true };
tmr.Tick += delegate {
frame++;
if (frame >= delays.Length) frame = 0;
img.SelectActiveFrame(FrameDimension.Page, frame);
tmr.Interval = delays[frame];
ctl.Invalidate();
};
ctl.Disposed += delegate { tmr.Dispose(); };
}
使用示例:
public Form1() {
InitializeComponent();
pictureBox1.Image = CreateAnimation(pictureBox1,
new Image[] { Properties.Resources.Frame1, Properties.Resources.Frame2, Properties.Resources.Frame3 },
new int[] { 1000, 2000, 300 });
}
更聪明的方法是完全放弃返回值的要求,这样就不必生成TIFF。只需使用Animate()方法,并带有一个Action<Image>参数来更新控件的属性。但这并不是你要求的内容。