相对于 WinForm PictureBox 控件原生支持动态 GIF,WPF Image 控件却不支持,让人摸不着头脑
常用方法
提到 WPF 播放动图,常见的方法有三种
MediaElement
使用 MediaElement 控件,缺点是依赖 Media Player,且不支持透明- [/code][size=4]WinForm PictureBox[/size]
- 借助 WindowsFormsIntegration 嵌入 WinForm PictureBox,缺点是不支持透明
- [code]<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>
复制代码 WpfAnimatedGif
引用 NuGet 包 WpfAnimatedGif,支持透明- [/code]作者还有另一个性能更好、跨平台的 XamlAnimatedGif,用法相同
- [size=5]原生解码方法[/size]
- WPF 虽然原生 Image 不支持 GIF 动图,但是提供了 GifBitmapDecoder 解码器,可以获取元数据,包括循环信息、逻辑尺寸、所有帧信息等
- [size=4]判断是否循环和循环次数[/size]
- [code]int loop = 1;bool isAnimated = true;var decoder = new GifBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);var data = decoder.Metadata;if (data.GetQuery("/appext/Application") is byte[] array1){<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>string appName = Encoding.ASCII.GetString(array1);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>if ((appName == "NETSCAPE2.0" || appName == "ANIMEXTS1.0")<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>&& data.GetQuery("/appext/Data") is byte[] array2)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>loop = array2[2] | array2[3] (Uri)GetValue(UriSourceProperty);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>set => SetValue(UriSourceProperty, value);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>public Stream StreamSource<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>get => (Stream)GetValue(StreamSourceProperty);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>set => SetValue(StreamSourceProperty, value);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>public int FrameIndex<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>get => (int)GetValue(FrameIndexProperty);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>private set => SetValue(FrameIndexProperty, value);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>public Stretch Stretch<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>get => (Stretch)GetValue(StretchProperty);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>set => SetValue(StretchProperty, value);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>public StretchDirection StretchDirection<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>get => (StretchDirection)GetValue(StretchDirectionProperty);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>set => SetValue(StretchDirectionProperty, value);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>public bool IsLoading<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>get => (bool)GetValue(IsLoadingProperty);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>set => SetValue(IsLoadingProperty, value);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>((GifImage)d)?.OnSourceChanged();<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>private static void OnFrameIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>((GifImage)d)?.OnFrameIndexChanged();<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>private static void OnStrechChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>if (d is GifImage image && image.Content is Viewbox viewbox)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>viewbox.Stretch = image.Stretch;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>private static void OnStrechDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>if (d is GifImage image && image.Content is Viewbox viewbox)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>viewbox.StretchDirection = image.StretchDirection;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>Stream stream;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>Canvas canvas;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>FrameInfo[] frameInfos;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>Int32AnimationUsingKeyFrames animation;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>public GifImage()<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>IsVisibleChanged += OnIsVisibleChanged;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>Unloaded += OnUnloaded;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>private void OnUnloaded(object sender, RoutedEventArgs e)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>Release();<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>if (IsVisible)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>StartAnimation();<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>else<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>StopAnimation();<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>private void StartAnimation()<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>BeginAnimation(FrameIndexProperty, animation);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>private void StopAnimation()<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>BeginAnimation(FrameIndexProperty, null);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>private void Release()<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>StopAnimation();<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>canvas?.Children.Clear();<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>stream?.Dispose();<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>animation = null;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>frameInfos = null;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>private async void OnSourceChanged()<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>Release();<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>IsLoading = true;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>FrameIndex = 0;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>if (UriSource != null)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>stream = await ResourceHelper.GetStream(UriSource);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>else<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>stream = StreamSource;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>if (stream != null)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>int loop = 1;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>bool isAnimated = true;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>var decoder = new GifBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>var data = decoder.Metadata;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>if (data.GetQuery("/appext/Application") is byte[] array1)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>string appName = Encoding.ASCII.GetString(array1);<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>if ((appName == "NETSCAPE2.0" || appName == "ANIMEXTS1.0")<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>&& data.GetQuery("/appext/Data") is byte[] array2)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>loop = array2[2] | array2[3] 0)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>var previousInfo = frameInfos[index - 1];<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>switch (previousInfo.DisposalMethod)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>case DisposalMethod.RestoreBackground:<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>// 隐藏之前的所有帧<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>for (int i = 0; i < index - 1; i++)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>frameInfos[i].Frame.Visibility = Visibility.Hidden;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>break;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>case DisposalMethod.RestorePrevious:<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>// 隐藏上一帧<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>previousInfo.Frame.Visibility = Visibility.Hidden;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>break;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>else<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>// 重新循环, 只显示第一帧<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>for (int i = 1; i < frameInfos.Length; i++)<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>{<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>frameInfos[i].Frame.Visibility = Visibility.Hidden;<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost><WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}<WindowsFormsHost>
- <wf:PictureBox x:Name="winFormsPictureBox"/>
- </WindowsFormsHost>}}
复制代码 使用到的从 URL 获取图像流的方法
调用示例
- [/code][size=5]ImageAnimator[/size]
- WinForm 中播放 GIF 用到了 ImageAnimator,利用它也可以在 WPF 中实现 GIF 动图控件,但其是基于 GDI 的方法,更推荐性能更好、支持硬解的解码器方法
- [code]using System;
- using System.IO;
- using System.Text;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
- using System.Windows.Media.Animation;
- using System.Windows.Media.Imaging;
- public sealed class GifImage : ContentControl
- {
- /// <summary>当前帧播放完成后的处理方法</summary>
- enum DisposalMethod
- {
- /// <summary>被全尺寸不透明的下一帧覆盖替换</summary>
- None,
- /// <summary>不丢弃, 继续显示下一帧未覆盖的任何像素</summary>
- DoNotDispose,
- /// <summary>重置到背景色</summary>
- RestoreBackground,
- /// <summary>恢复到上一个未释放的帧的状态</summary>
- RestorePrevious,
- }
- sealed class FrameInfo
- {
- public Image Frame { get; }
- public int DelayTime { get; }
- public DisposalMethod DisposalMethod { get; }
- public FrameInfo(BitmapFrame frame)
- {
- Frame = new Image { Source = frame };
- var data = (BitmapMetadata)frame.Metadata;
- DelayTime = Convert.ToUInt16(data.GetQuery("/grctlext/Delay"));
- DisposalMethod = (DisposalMethod)Convert.ToByte(data.GetQuery("/grctlext/Disposal"));
- ushort left = Convert.ToUInt16(data.GetQuery("/imgdesc/Left"));
- ushort top = Convert.ToUInt16(data.GetQuery("/imgdesc/Top"));
- ushort width = Convert.ToUInt16(data.GetQuery("/imgdesc/Width"));
- ushort height = Convert.ToUInt16(data.GetQuery("/imgdesc/Height"));
- Canvas.SetLeft(Frame, left);
- Canvas.SetTop(Frame, top);
- Canvas.SetRight(Frame, left + width);
- Canvas.SetBottom(Frame, top + height);
- }
- }
- public static readonly DependencyProperty UriSourceProperty =
- DependencyProperty.Register(nameof(UriSource), typeof(Uri), typeof(GifImage), new PropertyMetadata(null, OnSourceChanged));
- public static readonly DependencyProperty StreamSourceProperty =
- DependencyProperty.Register(nameof(StreamSource), typeof(Stream), typeof(GifImage), new PropertyMetadata(null, OnSourceChanged));
- public static readonly DependencyProperty FrameIndexProperty =
- DependencyProperty.Register(nameof(FrameIndex), typeof(int), typeof(GifImage), new PropertyMetadata(0, OnFrameIndexChanged));
- public static readonly DependencyProperty StretchProperty =
- DependencyProperty.Register(nameof(Stretch), typeof(Stretch), typeof(GifImage), new PropertyMetadata(Stretch.None, OnStrechChanged));
- public static readonly DependencyProperty StretchDirectionProperty =
- DependencyProperty.Register(nameof(StretchDirection), typeof(StretchDirection), typeof(GifImage), new PropertyMetadata(StretchDirection.Both, OnStrechDirectionChanged));
- public static readonly DependencyProperty IsLoadingProperty =
- DependencyProperty.Register(nameof(IsLoading), typeof(bool), typeof(GifImage), new PropertyMetadata(false));
- public Uri UriSource
- {
- get => (Uri)GetValue(UriSourceProperty);
- set => SetValue(UriSourceProperty, value);
- }
- public Stream StreamSource
- {
- get => (Stream)GetValue(StreamSourceProperty);
- set => SetValue(StreamSourceProperty, value);
- }
- public int FrameIndex
- {
- get => (int)GetValue(FrameIndexProperty);
- private set => SetValue(FrameIndexProperty, value);
- }
- public Stretch Stretch
- {
- get => (Stretch)GetValue(StretchProperty);
- set => SetValue(StretchProperty, value);
- }
- public StretchDirection StretchDirection
- {
- get => (StretchDirection)GetValue(StretchDirectionProperty);
- set => SetValue(StretchDirectionProperty, value);
- }
- public bool IsLoading
- {
- get => (bool)GetValue(IsLoadingProperty);
- set => SetValue(IsLoadingProperty, value);
- }
- private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- ((GifImage)d)?.OnSourceChanged();
- }
- private static void OnFrameIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- ((GifImage)d)?.OnFrameIndexChanged();
- }
- private static void OnStrechChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (d is GifImage image && image.Content is Viewbox viewbox)
- {
- viewbox.Stretch = image.Stretch;
- }
- }
- private static void OnStrechDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (d is GifImage image && image.Content is Viewbox viewbox)
- {
- viewbox.StretchDirection = image.StretchDirection;
- }
- }
- Stream stream;
- Canvas canvas;
- FrameInfo[] frameInfos;
- Int32AnimationUsingKeyFrames animation;
- public GifImage()
- {
- IsVisibleChanged += OnIsVisibleChanged;
- Unloaded += OnUnloaded;
- }
- private void OnUnloaded(object sender, RoutedEventArgs e)
- {
- Release();
- }
- private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
- {
- if (IsVisible)
- {
- StartAnimation();
- }
- else
- {
- StopAnimation();
- }
- }
- private void StartAnimation()
- {
- BeginAnimation(FrameIndexProperty, animation);
- }
- private void StopAnimation()
- {
- BeginAnimation(FrameIndexProperty, null);
- }
- private void Release()
- {
- StopAnimation();
- canvas?.Children.Clear();
- stream?.Dispose();
- animation = null;
- frameInfos = null;
- }
- private async void OnSourceChanged()
- {
- Release();
- IsLoading = true;
- FrameIndex = 0;
- if (UriSource != null)
- {
- stream = await ResourceHelper.GetStream(UriSource);
- }
- else
- {
- stream = StreamSource;
- }
- if (stream != null)
- {
- int loop = 1;
- bool isAnimated = true;
- var decoder = new GifBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
- var data = decoder.Metadata;
- if (data.GetQuery("/appext/Application") is byte[] array1)
- {
- string appName = Encoding.ASCII.GetString(array1);
- if ((appName == "NETSCAPE2.0" || appName == "ANIMEXTS1.0")
- && data.GetQuery("/appext/Data") is byte[] array2)
- {
- loop = array2[2] | array2[3] << 8;// 获取循环次数, 0表示无限循环
- isAnimated = array2[1] == 1;
- }
- }
- if (!(Content is Viewbox viewbox))
- {
- Content = viewbox = new Viewbox
- {
- Stretch = Stretch,
- StretchDirection = StretchDirection,
- };
- }
- if (canvas == null || canvas.Parent != Content)
- {
- canvas = new Canvas();
- viewbox.Child = canvas;
- }
- canvas.Width = Convert.ToUInt16(data.GetQuery("/logscrdesc/Width"));
- canvas.Height = Convert.ToUInt16(data.GetQuery("/logscrdesc/Height"));
- int count = decoder.Frames.Count;
- frameInfos = new FrameInfo[count];
- for (int i = 0; i < count; i++)
- {
- var info = new FrameInfo(decoder.Frames[i]);
- Image frame = info.Frame;
- frameInfos[i] = info;
- canvas.Children.Add(frame);
- Panel.SetZIndex(frame, i);
- canvas.Width = Math.Max(canvas.Width, Canvas.GetRight(frame));
- canvas.Height = Math.Max(canvas.Height, Canvas.GetBottom(frame));
- }
- OnFrameIndexChanged();
- if (isAnimated)
- {
- var keyFrames = new Int32KeyFrameCollection();
- var last = TimeSpan.Zero;
- for (int i = 0; i < frameInfos.Length; i++)
- {
- last += TimeSpan.FromMilliseconds(frameInfos[i].DelayTime * 10);
- keyFrames.Add(new DiscreteInt32KeyFrame(i, last));
- }
- animation = new Int32AnimationUsingKeyFrames
- {
- KeyFrames = keyFrames,
- RepeatBehavior = loop == 0 ? RepeatBehavior.Forever : new RepeatBehavior(loop)
- };
- StartAnimation();
- }
- }
- IsLoading = false;
- }
- private void OnFrameIndexChanged()
- {
- if (frameInfos != null)
- {
- int index = FrameIndex;
- frameInfos[index].Frame.Visibility = Visibility.Visible;
- if (index > 0)
- {
- var previousInfo = frameInfos[index - 1];
- switch (previousInfo.DisposalMethod)
- {
- case DisposalMethod.RestoreBackground:
- // 隐藏之前的所有帧
- for (int i = 0; i < index - 1; i++)
- {
- frameInfos[i].Frame.Visibility = Visibility.Hidden;
- }
- break;
- case DisposalMethod.RestorePrevious:
- // 隐藏上一帧
- previousInfo.Frame.Visibility = Visibility.Hidden;
- break;
- }
- }
- else
- {
- // 重新循环, 只显示第一帧
- for (int i = 1; i < frameInfos.Length; i++)
- {
- frameInfos[i].Frame.Visibility = Visibility.Hidden;
- }
- }
- }
- }
- }
复制代码 透明 GIF
GIF 本身只有 256 色,没有 Alpha 通道,但其仍支持透明,是通过其特殊的自定义颜色表调色盘实现的
上图是一张单帧透明 GIF,使用 Windows 自带画图打开,会错误显示为橙色背景
放入 WinForm PictureBox 中,Win7 和较旧的 Win10 也会错误显示为橙色背景
但最新的 Win11 和 Win10 上会显示为透明背景,猜测是近期 Win11 在截图工具中推出了录制 GIF 功能时顺手更新了 .NET System.Drawing GIF 解析方法,Win10 也收到了这次补丁更新
不过使用 WPF 解码器方法能过获得正确的背景
相关资料
Table of Contents
Native Image Format Metadata Queries - Win32 apps
WICGifGraphicControlExtensionProperties (wincodec.h) - Win32 apps | Microsoft Learn
WICGifImageDescriptorProperties (wincodec.h) - Win32 apps | Microsoft Learn
[WPF疑难]在WPF中显示动态GIF - 周银辉 - 博客园
wpf GifBitmapDecoder 解析 gif 格式
浓缩的才是精华:浅析GIF格式图片的存储和压缩 - 腾讯云开发者 - 博客园
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |