【IT168技术文档】
在我们寻求帮助的时候,最不愿意听到的答复是:很抱歉,在当前版本的产品中还没有实现该功能... 在WPF中显示动态的GIF图像时便遇到了这样的问题,WPF中强大的Image控件却不支持动态的GIF(其只能显示第一帧).当然,我们可以说WPF 强大的动画能力,让我们完全有理由抛弃传统的GIF动画,但如某种情况下如果你觉得使用动态的GIF更合适的话(比如QQ表情,因为GIF是利于保存和传输的),没关系,本篇随笔将帮助你解决这个问题.
1,曾有过的尝试:
我们在实际开发过程中也遇到显示动态GIF的问题.发现普通的Image控件不能正常显示后,我们又发现网页浏览器却是可以的,以及 windows XP的"图片和传真查看器"也可以,但"Window Live照片库"却不可以.所以我们最初打算使用通过包装WebBrowseControl来实现,即是在WPF中host一个.net2.0中的浏览器控件,然后让该浏览器来实现图片,成功了,但麻烦的事情是
鼠标右键可以点出网页的上下文菜单.我们放弃了该方案,除了不愿意花时间来屏蔽上下文菜单和浏览器控件的多余功能外,同时我们的觉得浏览器控件过于"重量级",有点杀鸡用牛刀的感觉.另外,你可能会想到使用WPF中的Frame控件,但也会得到上述结果.另外,有网友说可以使用MediaElement控件,但大都没有成功,我也没有(可能是RP不够哈,呵呵...)
2,GifBitmapDecoder
我们发现WPF中有一个名为GifBitmapDecoder的类,其可以将动态GIF分解成很多帧并保存在一个列表中,每一帧为一个BitmapFrame类型的对象,其父类为BitmapSource,这也就意味着,我们可以将每一帧赋值给一个Image控件的Source属性,这样我们可以得到针对GIF各帧的Image系列:
GifBitmapDecoder decoder = new GifBitmapDecoder(
new Uri("OH.gif", UriKind.Relative),
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
foreach (BitmapFrame f in decoder.Frames)
{
Image image = new Image();
image.Source = f;
this.panel1.Children.Add(image);
}
3,解析GIF
要解析文件就必须知道文件的
存储结构,比如,得到帧的显示时间的方法是这样的:
private int ParseGraphicControlExtension(byte[] gifData, int offset)
{
int returnOffset = offset;
// Extension Block
int length = gifData[offset + 2];
returnOffset = offset + length + 2 + 1;
byte packedField = gifData[offset + 3];
currentParseGifFrame.disposalMethod = (packedField & 0x1C) >> 2;
// Get DelayTime
int delay = BitConverter.ToUInt16(gifData, offset + 4);
currentParseGifFrame.delayTime = delay;
while (gifData[returnOffset] != 0x00)
{
returnOffset = returnOffset + gifData[returnOffset] + 1;
}
returnOffset++;
return returnOffset;
}