WPF 显示gif
using System;
using System.IO;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Threading; namespace GifImageLib
{ class GifAnimation : Viewbox
{ private class GifFrame : Image
{ public int delayTime; public int disposalMethod; public int left; public int top; public int width; public int height;
} private Canvas canvas = null; private List<GifFrame> frameList = null; private int frameCounter = ;
private int numberOfFrames = ; private int numberOfLoops = -;
private int currentLoop = ; private int logicalWidth = ;
private int logicalHeight = ; private DispatcherTimer frameTimer = null; private GifFrame currentParseGifFrame; public GifAnimation()
{
canvas = new Canvas();
this.Child = canvas;
} private void Reset()
{
if (frameList != null)
{
frameList.Clear();
}
frameList = null;
frameCounter = ;
numberOfFrames = ;
numberOfLoops = -;
currentLoop = ;
logicalWidth = ;
logicalHeight = ;
if (frameTimer != null)
{
frameTimer.Stop();
frameTimer = null;
}
} #region PARSE
private void ParseGif(byte[] gifData)
{
frameList = new List<GifFrame>();
currentParseGifFrame = new GifFrame();
ParseGifDataStream(gifData, );
} private int ParseBlock(byte[] gifData, int offset)
{
switch (gifData[offset])
{
case 0x21:
if (gifData[offset + ] == 0xF9)
{
return ParseGraphicControlExtension(gifData, offset);
}
else
{
return ParseExtensionBlock(gifData, offset);
}
case 0x2C:
offset = ParseGraphicBlock(gifData, offset);
frameList.Add(currentParseGifFrame);
currentParseGifFrame = new GifFrame();
return offset;
case 0x3B:
return -;
default:
throw new Exception("GIF format incorrect: missing graphic block or special-purpose block. ");
}
} private int ParseGraphicControlExtension(byte[] gifData, int offset)
{
int returnOffset = offset;
int length = gifData[offset + ];
returnOffset = offset + length + + ; byte packedField = gifData[offset + ];
currentParseGifFrame.disposalMethod = (packedField & 0x1C) >> ; int delay = BitConverter.ToUInt16(gifData, offset + );
currentParseGifFrame.delayTime = delay;
while (gifData[returnOffset] != 0x00)
{
returnOffset = returnOffset + gifData[returnOffset] + ;
} returnOffset++; return returnOffset;
} private int ParseLogicalScreen(byte[] gifData, int offset)
{
logicalWidth = BitConverter.ToUInt16(gifData, offset);
logicalHeight = BitConverter.ToUInt16(gifData, offset + ); byte packedField = gifData[offset + ];
bool hasGlobalColorTable = (int)(packedField & 0x80) > ? true : false; int currentIndex = offset + ;
if (hasGlobalColorTable)
{
int colorTableLength = packedField & 0x07;
colorTableLength = (int)Math.Pow(, colorTableLength + ) * ;
currentIndex = currentIndex + colorTableLength;
}
return currentIndex;
} private int ParseGraphicBlock(byte[] gifData, int offset)
{
currentParseGifFrame.left = BitConverter.ToUInt16(gifData, offset + );
currentParseGifFrame.top = BitConverter.ToUInt16(gifData, offset + );
currentParseGifFrame.width = BitConverter.ToUInt16(gifData, offset + );
currentParseGifFrame.height = BitConverter.ToUInt16(gifData, offset + );
if (currentParseGifFrame.width > logicalWidth)
{
logicalWidth = currentParseGifFrame.width;
}
if (currentParseGifFrame.height > logicalHeight)
{
logicalHeight = currentParseGifFrame.height;
}
byte packedField = gifData[offset + ];
bool hasLocalColorTable = (int)(packedField & 0x80) > ? true : false; int currentIndex = offset + ;
if (hasLocalColorTable)
{
int colorTableLength = packedField & 0x07;
colorTableLength = (int)Math.Pow(, colorTableLength + ) * ;
currentIndex = currentIndex + colorTableLength;
}
currentIndex++; currentIndex++; while (gifData[currentIndex] != 0x00)
{
int length = gifData[currentIndex];
currentIndex = currentIndex + gifData[currentIndex];
currentIndex++;
}
currentIndex = currentIndex + ;
return currentIndex;
} private int ParseExtensionBlock(byte[] gifData, int offset)
{
int returnOffset = offset;
int length = gifData[offset + ];
returnOffset = offset + length + + ;
if (gifData[offset + ] == 0xFF && length > )
{
string netscape = System.Text.ASCIIEncoding.ASCII.GetString(gifData, offset + , );
if (netscape == "NETSCAPE")
{
numberOfLoops = BitConverter.ToUInt16(gifData, offset + );
if (numberOfLoops > )
{
numberOfLoops++;
}
}
}
while (gifData[returnOffset] != 0x00)
{
returnOffset = returnOffset + gifData[returnOffset] + ;
} returnOffset++; return returnOffset;
} private int ParseHeader(byte[] gifData, int offset)
{
string str = System.Text.ASCIIEncoding.ASCII.GetString(gifData, offset, );
if (str != "GIF")
{
throw new Exception("Not a proper GIF file: missing GIF header");
}
return ;
} private void ParseGifDataStream(byte[] gifData, int offset)
{
offset = ParseHeader(gifData, offset);
offset = ParseLogicalScreen(gifData, offset);
while (offset != -)
{
offset = ParseBlock(gifData, offset);
}
} #endregion public void CreateGifAnimation(MemoryStream memoryStream)
{
Reset(); byte[] gifData = memoryStream.GetBuffer(); // Use GetBuffer so that there is no memory copy GifBitmapDecoder decoder = new GifBitmapDecoder(memoryStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); numberOfFrames = decoder.Frames.Count; try
{
ParseGif(gifData);
}
catch
{
throw new FileFormatException("Unable to parse Gif file format.");
} for (int i = ; i < decoder.Frames.Count; i++)
{
frameList[i].Source = decoder.Frames[i];
frameList[i].Visibility = Visibility.Hidden;
canvas.Children.Add(frameList[i]);
Canvas.SetLeft(frameList[i], frameList[i].left);
Canvas.SetTop(frameList[i], frameList[i].top);
Canvas.SetZIndex(frameList[i], i);
}
canvas.Height = logicalHeight;
canvas.Width = logicalWidth; frameList[].Visibility = Visibility.Visible; for (int i = ; i < frameList.Count; i++)
{
Console.WriteLine(frameList[i].disposalMethod.ToString() + " " + frameList[i].width.ToString() + " " + frameList[i].delayTime.ToString());
} if (frameList.Count > )
{
if (numberOfLoops == -)
{
numberOfLoops = ;
}
frameTimer = new System.Windows.Threading.DispatcherTimer();
frameTimer.Tick += NextFrame;
frameTimer.Interval = new TimeSpan(, , , , frameList[].delayTime * );
frameTimer.Start();
}
} public void NextFrame()
{
NextFrame(null, null);
} public void NextFrame(object sender, EventArgs e)
{
frameTimer.Stop();
if (numberOfFrames == ) return;
if (frameList[frameCounter].disposalMethod == )
{
frameList[frameCounter].Visibility = Visibility.Hidden;
}
if (frameList[frameCounter].disposalMethod >= )
{
frameList[frameCounter].Visibility = Visibility.Hidden;
}
frameCounter++; if (frameCounter < numberOfFrames)
{
frameList[frameCounter].Visibility = Visibility.Visible;
frameTimer.Interval = new TimeSpan(, , , , frameList[frameCounter].delayTime * );
frameTimer.Start();
}
else
{
if (numberOfLoops != )
{
currentLoop++;
}
if (currentLoop < numberOfLoops || numberOfLoops == )
{
for (int f = ; f < frameList.Count; f++)
{
frameList[f].Visibility = Visibility.Hidden;
}
frameCounter = ;
frameList[frameCounter].Visibility = Visibility.Visible;
frameTimer.Interval = new TimeSpan(, , , , frameList[frameCounter].delayTime * );
frameTimer.Start();
}
}
}
}
}
GifAnimation
using System.Net;
using System.IO;
using System.Security;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Windows.Resources;
using System; namespace GifImageLib
{
public class GifImageExceptionRoutedEventArgs : RoutedEventArgs
{
public Exception ErrorException; public GifImageExceptionRoutedEventArgs(RoutedEvent routedEvent, object obj)
: base(routedEvent, obj)
{
}
} class WebReadState
{
public WebRequest webRequest;
public MemoryStream memoryStream;
public Stream readStream;
public byte[] buffer;
} public class GifImage : System.Windows.Controls.UserControl
{
private GifAnimation gifAnimation = null;
private Image image = null; public GifImage()
{
} public static readonly DependencyProperty ForceGifAnimProperty = DependencyProperty.Register("ForceGifAnim", typeof(bool), typeof(GifImage), new FrameworkPropertyMetadata(false));
public bool ForceGifAnim
{
get
{
return (bool)this.GetValue(ForceGifAnimProperty);
}
set
{
this.SetValue(ForceGifAnimProperty, value);
}
} public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(string), typeof(GifImage), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnSourceChanged)));
private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
GifImage obj = (GifImage)d;
string s = (string)e.NewValue;
obj.CreateFromSourceString(s);
}
public string Source
{
get
{
return (string)this.GetValue(SourceProperty);
}
set
{
this.SetValue(SourceProperty, value);
}
} public static readonly DependencyProperty StretchProperty = DependencyProperty.Register("Stretch", typeof(Stretch), typeof(GifImage), new FrameworkPropertyMetadata(Stretch.Fill, FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnStretchChanged)));
private static void OnStretchChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
GifImage obj = (GifImage)d;
Stretch s = (Stretch)e.NewValue;
if (obj.gifAnimation != null)
{
obj.gifAnimation.Stretch = s;
}
else if (obj.image != null)
{
obj.image.Stretch = s;
}
}
public Stretch Stretch
{
get
{
return (Stretch)this.GetValue(StretchProperty);
}
set
{
this.SetValue(StretchProperty, value);
}
} public static readonly DependencyProperty StretchDirectionProperty = DependencyProperty.Register("StretchDirection", typeof(StretchDirection), typeof(GifImage), new FrameworkPropertyMetadata(StretchDirection.Both, FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnStretchDirectionChanged)));
private static void OnStretchDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
GifImage obj = (GifImage)d;
StretchDirection s = (StretchDirection)e.NewValue;
if (obj.gifAnimation != null)
{
obj.gifAnimation.StretchDirection = s;
}
else if (obj.image != null)
{
obj.image.StretchDirection = s;
}
}
public StretchDirection StretchDirection
{
get
{
return (StretchDirection)this.GetValue(StretchDirectionProperty);
}
set
{
this.SetValue(StretchDirectionProperty, value);
}
} public delegate void ExceptionRoutedEventHandler(object sender, GifImageExceptionRoutedEventArgs args); public static readonly RoutedEvent ImageFailedEvent = EventManager.RegisterRoutedEvent("ImageFailed", RoutingStrategy.Bubble, typeof(ExceptionRoutedEventHandler), typeof(GifImage)); public event ExceptionRoutedEventHandler ImageFailed
{
add
{
AddHandler(ImageFailedEvent, value);
}
remove
{
RemoveHandler(ImageFailedEvent, value);
}
} void image_ImageFailed(object sender, ExceptionRoutedEventArgs e)
{
RaiseImageFailedEvent(e.ErrorException);
} void RaiseImageFailedEvent(Exception exp)
{
GifImageExceptionRoutedEventArgs newArgs = new GifImageExceptionRoutedEventArgs(ImageFailedEvent, this);
newArgs.ErrorException = exp;
RaiseEvent(newArgs);
} private void DeletePreviousImage()
{
if (image != null)
{
this.RemoveLogicalChild(image);
image = null;
}
if (gifAnimation != null)
{
this.RemoveLogicalChild(gifAnimation);
gifAnimation = null;
}
} private void CreateNonGifAnimationImage()
{
image = new Image();
image.ImageFailed += new EventHandler<ExceptionRoutedEventArgs>(image_ImageFailed);
ImageSource src = (ImageSource)(new ImageSourceConverter().ConvertFromString(Source));
image.Source = src;
image.Stretch = Stretch;
image.StretchDirection = StretchDirection;
this.AddChild(image);
} private void CreateGifAnimation(MemoryStream memoryStream)
{
gifAnimation = new GifAnimation();
gifAnimation.CreateGifAnimation(memoryStream);
gifAnimation.Stretch = Stretch;
gifAnimation.StretchDirection = StretchDirection;
this.AddChild(gifAnimation);
} private void CreateFromSourceString(string source)
{
DeletePreviousImage();
Uri uri; try
{
uri = new Uri(source, UriKind.RelativeOrAbsolute);
}
catch (Exception exp)
{
RaiseImageFailedEvent(exp);
return;
} if (source.Trim().ToUpper().EndsWith(".GIF") || ForceGifAnim)
{
if (!uri.IsAbsoluteUri)
{
GetGifStreamFromPack(uri);
}
else
{ string leftPart = uri.GetLeftPart(UriPartial.Scheme); if (leftPart == "http://" || leftPart == "ftp://" || leftPart == "file://")
{
GetGifStreamFromHttp(uri);
}
else if (leftPart == "pack://")
{
GetGifStreamFromPack(uri);
}
else
{
CreateNonGifAnimationImage();
}
}
}
else
{
CreateNonGifAnimationImage();
}
} private delegate void WebRequestFinishedDelegate(MemoryStream memoryStream); private void WebRequestFinished(MemoryStream memoryStream)
{
CreateGifAnimation(memoryStream);
} private delegate void WebRequestErrorDelegate(Exception exp); private void WebRequestError(Exception exp)
{
RaiseImageFailedEvent(exp);
} private void WebResponseCallback(IAsyncResult asyncResult)
{
WebReadState webReadState = (WebReadState)asyncResult.AsyncState;
WebResponse webResponse;
try
{
webResponse = webReadState.webRequest.EndGetResponse(asyncResult);
webReadState.readStream = webResponse.GetResponseStream();
webReadState.buffer = new byte[];
webReadState.readStream.BeginRead(webReadState.buffer, , webReadState.buffer.Length, new AsyncCallback(WebReadCallback), webReadState);
}
catch (WebException exp)
{
this.Dispatcher.Invoke(DispatcherPriority.Render, new WebRequestErrorDelegate(WebRequestError), exp);
}
} private void WebReadCallback(IAsyncResult asyncResult)
{
WebReadState webReadState = (WebReadState)asyncResult.AsyncState;
int count = webReadState.readStream.EndRead(asyncResult);
if (count > )
{
webReadState.memoryStream.Write(webReadState.buffer, , count);
try
{
webReadState.readStream.BeginRead(webReadState.buffer, , webReadState.buffer.Length, new AsyncCallback(WebReadCallback), webReadState);
}
catch (WebException exp)
{
this.Dispatcher.Invoke(DispatcherPriority.Render, new WebRequestErrorDelegate(WebRequestError), exp);
}
}
else
{
this.Dispatcher.Invoke(DispatcherPriority.Render, new WebRequestFinishedDelegate(WebRequestFinished), webReadState.memoryStream);
}
} private void GetGifStreamFromHttp(Uri uri)
{
try
{
WebReadState webReadState = new WebReadState();
webReadState.memoryStream = new MemoryStream();
webReadState.webRequest = WebRequest.Create(uri);
webReadState.webRequest.Timeout = ; webReadState.webRequest.BeginGetResponse(new AsyncCallback(WebResponseCallback), webReadState);
}
catch (SecurityException)
{
CreateNonGifAnimationImage();
}
} private void ReadGifStreamSynch(Stream s)
{
byte[] gifData;
MemoryStream memoryStream;
using (s)
{
memoryStream = new MemoryStream((int)s.Length);
BinaryReader br = new BinaryReader(s);
gifData = br.ReadBytes((int)s.Length);
memoryStream.Write(gifData, , (int)s.Length);
memoryStream.Flush();
}
CreateGifAnimation(memoryStream);
} private void GetGifStreamFromPack(Uri uri)
{
try
{
StreamResourceInfo streamInfo; if (!uri.IsAbsoluteUri)
{
streamInfo = Application.GetContentStream(uri);
if (streamInfo == null)
{
streamInfo = Application.GetResourceStream(uri);
}
}
else
{
if (uri.GetLeftPart(UriPartial.Authority).Contains("siteoforigin"))
{
streamInfo = Application.GetRemoteStream(uri);
}
else
{
streamInfo = Application.GetContentStream(uri);
if (streamInfo == null)
{
streamInfo = Application.GetResourceStream(uri);
}
}
}
if (streamInfo == null)
{
throw new FileNotFoundException("Resource not found.", uri.ToString());
}
ReadGifStreamSynch(streamInfo.Stream);
}
catch (Exception exp)
{
RaiseImageFailedEvent(exp);
}
}
}
}
GifImage
使用:
var image = new GifImage { Source = "Path", Stretch = Stretch.Fill };
WPF 显示gif的更多相关文章
- C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试(续)
介绍 本文是接着上文<C# WPF 显示图片和视频显示 EmuguCv.AForge.Net测试>写的,建议先看下上文,因为有些代码还需要了解. 增添 接着上文的代码,我们可以在事件处理方 ...
- WPF显示图片
1.WPF显示图片内部一部分 <Rectangle Height="> <Rectangle.Fill > <ImageBrush ImageSource=&q ...
- WPF显示html的几种方法
原文:WPF显示html的几种方法 客户希望系统在一些特定的条件下,界面上能显示用户自定义的格式和内容,格式和内容通过html指定. 基本上在wpf中显示html有以下四种方法. 1. W ...
- C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试
WPF 没有用到 PictureBox, 而是用Image代替. 下面我试着加载显示一个图片 . XAML <Image x:Name="srcImg"Width=" ...
- WPF 显示初始化界面
今天在看<WPF编程宝典>时,看到了Application类,该类可以做很多事情,我认为比较实用的是显示初始化界面,因为之前有个项目在打开的时候要加载好多dll,非常耗时,让客户等的蛋疼, ...
- WPF 显示模态窗口和窗体
<WPF编程宝典——使用C# 2008和.NET 3.5(第2版)>第25章与Windows窗体的互操作,本章将介绍用于集成Windows窗体和WPF内容的不同策略.还将分析如何在应用程序 ...
- wpf显示视频,image控件闪屏,使用winform控件实现
使用C#调用mingw的动态库实现视频识别软件,程序通过C++调用opencv打开视频,将图像的原始数据以rgb24的方式传递给C#端,C#通过构造图像对象给控件赋值的方式显示图片. 一开始使用wpf ...
- WPF 显示3D密集场景,堆场管理系统
又好久好久没写博客了,这次接着上文https://www.cnblogs.com/CSSZBB/p/12785380.html,上文用WPF 的绘图功能,制作了一个伪3D的2.5D控件ThreeDBo ...
- WPF显示GIF图的几种方式
使用MediaElement 这种方式有一个局限就是图片路径必须是绝对路径 <MediaElement Source="file://C:\129.gif" /> 并且 ...
- WPF 显示GIF动画
简单的通过GifBitmapDecoder解析GIF图片,获取gif帧数和每一帧数据,然后通过时间切换显示,效果如下: 代码如下: namespace GIfImageApplication { pu ...
随机推荐
- Got a packet bigger than 'max_allowed_packet' bytes
昨天用导入数据的时候发现有的地方有这个错误.后来才发现我用RPM包装的MYSQL配置文件里面有old_passwords=1去掉就可以了. Got a packet bigger than ‘max_ ...
- 添加web引用和添加服务引用有什么区别?
添加web引用和添加服务引用有什么区别,Add Service References 和 Add Web References 有啥区别?参考 http://social.microsoft.com/ ...
- 工作随笔——CentOS6.4支持rz sz操作
yum一句话解决: yum -y install lrzsz
- 工作随笔——tar命令批量解压
由于linux的tar命令不支持批量解压,所以很多网友编写了好多支持批量解压的shell命令,收集了一下,供大家分享: 第一: for tar in *.tar.gz; do tar xvf $tar ...
- 分享:大晚上用自己的锤子手机跨系统刷MIUI,跌宕起伏啊!!
序言: 写这篇博客之前问了一下博客园官方,能不能写关于刷机这一方面的,官方还是比较通情达理的,说技术类没有限制的,那样我就放心的写了.今天早上在博客园中稍微逛了一下,感觉似乎很少有关于刷机这一方面的, ...
- Android中的异步网络请求
本篇文章我们来一起写一个最基本的Android异步网络请求框架,借此来了解下Android中网络请求的相关姿势.由于个人水平有限,文中难免存在疏忽和谬误,希望大家可以指出,谢谢大家:) 1. 同步网络 ...
- 【JVM】模板解释器--字节码的resolve过程
1.背景 上文探讨了:[JVM]模板解释器--如何根据字节码生成汇编码? 本篇,我们来关注下字节码的resolve过程. 2.问题及准备工作 上文虽然探讨了字节码到汇编码的过程,但是: mov %ra ...
- LinuxMint(同Ubuntu)下安装配置NFS设置共享目录
假设有两台机器, 机器A:10.68.93.2 机器B:10.68.93.3 现在需要将机器A上的/opt/nfsshare共享出去,然后挂载到机器B的/nfsshare目录下. 1. 在机器A上: ...
- jQuery使用之(一)标记元素属性
jQuery使用主要介绍jQuery如何控制页面,包含元素的属性.css样式风格.DOM模型.表单元素和事件处理等. 标记元素的属性 html中每一个标记都具有一些属性,他们这个标记在页面中呈现各种状 ...
- java的RMI(Remote Method Invocation)
RMI 相关知识RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络 ...