在網上有很多圖片都是gif,那麼如何在 wpf 解析 gif? 本文告訴大家如何使用 GifBitmapDecoder 把gif分開為一張一張,獲得他的信息 ...
在網上有很多圖片都是gif,那麼如何在 wpf 解析 gif?
本文告訴大家如何使用 GifBitmapDecoder 把gif分開為一張一張,獲得他的信息。
如果需要把一個 gif 分開,使用的代碼很簡單
var file = "E:\\林德熙\\測試文件\\2017年9月1日 10.gif";
var stream = new FileStream(file, FileMode.Open);
var decoder = new GifBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
從 decoder 就可以獲得每個圖片,例如寫一個按鈕,按一下就切換一個圖片。
private int n = 0;
private void Button_OnClick(object sender, RoutedEventArgs e)
{
var t = decoder.Frames[n];
Image.Source = t;
n++;
if (n >= decoder.Frames.Count)
{
n = 0;
}
}
按鈕點擊如上面代碼,可以看到 decoder 把 gif 分開很簡單,但是如何獲得一幀的時間。如果在 wpf 獲得 gif 圖片間隔,就需要一些特殊方法。
先創建一個類 用於獲得 gif 的信息,需要知道,每個gif的裡面的圖片都有信息。
class FrameInfo
{
public TimeSpan Delay { get; set; }
public FrameDisposalMethod DisposalMethod { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public double Left { get; set; }
public double Top { get; set; }
public Rect Rect
{
get { return new Rect(Left, Top, Width, Height); }
}
}
其中 Delay
就是兩個圖片播放的時間,FrameDisposalMethod
表示兩張圖片是如何播放,完全替換前一張還是在前一張基礎繼續顯示。
獲得 gif 的信息需要使用 GetQuery
,這個方法不好用,於是使用下麵代碼把他轉類型
private static T? GetQueryOrNull<T>(this BitmapMetadata metadata, string query)
where T : struct
{
if (metadata.ContainsQuery(query))
{
object value = metadata.GetQuery(query);
if (value != null)
return (T) value;
}
return null;
}
可以看到 decoder 的每個圖片的 Metadata
是 ImageMetadata
,而且wr也沒說它裡面有哪些數據。
實際可以使用BitmapMetadata
獲得每個圖片信息,因為Metadata
實際是BitmapMetadata
,通過/grctlext/Delay
可以獲得兩個圖片的時間,/grctlext/Disposal
可以獲得兩個圖片是如何顯示,/imgdesc/Width
可以獲得寬度。於是使用下麵函數可以獲得圖片信息
public static FrameInfo GetFrameInfo(BitmapFrame frame)
{
var frameInfo = new FrameInfo
{
Delay = TimeSpan.FromMilliseconds(100),
DisposalMethod = FrameDisposalMethod.Replace,
Width = frame.PixelWidth,
Height = frame.PixelHeight,
Left = 0,
Top = 0
};
BitmapMetadata metadata;
try
{
metadata = frame.Metadata as BitmapMetadata;
if (metadata != null)
{
const string delayQuery = "/grctlext/Delay";
const string disposalQuery = "/grctlext/Disposal";
const string widthQuery = "/imgdesc/Width";
const string heightQuery = "/imgdesc/Height";
const string leftQuery = "/imgdesc/Left";
const string topQuery = "/imgdesc/Top";
var delay = metadata.GetQueryOrNull<ushort>(delayQuery);
if (delay.HasValue)
frameInfo.Delay = TimeSpan.FromMilliseconds(10 * delay.Value);
var disposal = metadata.GetQueryOrNull<byte>(disposalQuery);
if (disposal.HasValue)
frameInfo.DisposalMethod = (FrameDisposalMethod) disposal.Value;
var width = metadata.GetQueryOrNull<ushort>(widthQuery);
if (width.HasValue)
frameInfo.Width = width.Value;
var height = metadata.GetQueryOrNull<ushort>(heightQuery);
if (height.HasValue)
frameInfo.Height = height.Value;
var left = metadata.GetQueryOrNull<ushort>(leftQuery);
if (left.HasValue)
frameInfo.Left = left.Value;
var top = metadata.GetQueryOrNull<ushort>(topQuery);
if (top.HasValue)
frameInfo.Top = top.Value;
}
}
catch (NotSupportedException)
{
}
return frameInfo;
}
參見: http://www.thomaslevesque.com/2011/03/27/wpf-display-an-animated-gif-image/
http://stackoverflow.com/questions/210922/how-do-i-get-an-animated-gif-to-work-in-wpf
本作品採用知識共用署名-非商業性使用-相同方式共用 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發佈,但務必保留文章署名林德熙(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我聯繫。