目录 - Table of Contents

WPF 图像处理

以前一直都是用 WinForm 写窗体,最近准备转向WPF,然而尝试之后,我发现WPF的设计思路与Windows有许多差别,比如最简单的图片控件,就有许多的坑等着你去踩。

因为在WPF中,无法直接应用 Bitmap 对象到 Image 控件之中,而 Image 控件一般情况下只能通过读取URI才能加载图片。
通过一番google和摸索后,我总算是总结了一些 Image 控件的应用技巧,做个记录防止忘了,也顺便分享一下。

以下示例中,XAML中拥有一个名为 img 的 Image 控件!
<Image Name="img"></Image>

正常加载流程

<Image Name="img" Source="xxx/xxx.jpg"></Image>
Dim image As New BitmapImage
image.BeginInit()
image.UriSource = New Uri("xxx/xxx.jpg") '读取图片路径
image.EndInit()

img.Source = image '为Image标签赋值Source对象,加载并显示图片

将 Bitmap 转换为 BitmapSource

WPF工程默认不会导入Windows窗体类库,因此您需要先自行导入 System.Drawing.dll 类库。
Shared Function BitmapToBitmapSource(bmp As System.Drawing.Bitmap) As BitmapSource
    Dim ret As BitmapSource
    Try
        ret = Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions)
    Catch ex As Exception
        ret = Nothing
    End Try
    Return ret
End Function

将 Bytes 或 MemoryStream 转换为 BitmapSource

Shared Function BytesToBitmapSource(bytes As Byte()) As BitmapSource
    Dim ms As New IO.MemoryStream
    ms.Write(bytes, 0, bytes.Length)
    Return MemoryStreamToBitmapSource(ms)
End Function

Shared Function MemoryStreamToBitmapSource(ms As System.IO.MemoryStream) As BitmapSource
    Dim ret As New BitmapImage
    ret.BeginInit()
    ret.StreamSource = ms '就是这么简单
    ret.EndInit()
    'ms.Dispose() '不要尝试清除内存流,否则会导致图片失效
    Return ret
End Function

加载GIF动画

在 WPF 之中,默认的 Image 控件是无法加载GIF动画的,因此需要你下载一个 WpfAnimatedGif 组件!
github https://github.com/XamlAnimatedGif/WpfAnimatedGif
nuget https://www.nuget.org/packages/WpfAnimatedGif

安装完组件之后,在需要应用GIF动画的XAML代码中,应用下面的代码:
<Window x:Class="demo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:gif="http://wpfanimatedgif.codeplex.com" 
>
    <Grid>
        <Image Name="img" gif:ImageBehavior.AnimatedSource=".../xxx.gif" />
    </Grid>
</Window>
其中 Window 标签内的属性 xmlns:gif="http://wpfanimatedgif.codeplex.com" 是应用 WpfAnimatedGif 的关键,请一定记得添加上!
(也可以使用 xmlns:gif="clr-namespace:WpfAnimatedGif;assembly=WpfAnimatedGif" 来声明)

之后,如果你想直接在XAML中加载GIF动画,只需要将原本的 Source 属性修改为 gif:ImageBehavior.AnimatedSource,用来加载GIF动画!

如果你想要用代码完成动画加载,只需要参考下面的示例:
(记得先导入命名空间 Imports WpfAnimatedGif
Dim image = New BitmapImage()
image.BeginInit()
image.UriSource = New Uri(".../xxx.gif")
image.EndInit()

ImageBehavior.SetAnimatedSource(img, image) '设置动画源,无需调用 img.Source = image

重复次数

设置重复很简单,只需应用 gif:ImageBehavior.RepeatBehavior 属性即可。
<Image Name="img"
       gif:ImageBehavior.RepeatBehavior="3x"
       gif:ImageBehavior.AnimatedSource="xxx.gif"
/>
参数 3x 代表重复播放3次;
你也可以设置为时间格式 0:0:10 表示只播放10秒钟;
参数 Forever0x 表示永远播放。

代码控制示例:
' 重复3次
ImageBehavior.SetRepeatBehavior(img, new Animation.RepeatBehavior(3));

' 播放10秒
ImageBehavior.SetRepeatBehavior(img, new Animation.RepeatBehavior(TimeSpan.FromSeconds(10)));

' 无限重播
ImageBehavior.SetRepeatBehavior(img, Animation.RepeatBehavior.Forever);

' 最后别忘记设置一下源
ImageBehavior.SetAnimatedSource(img, image)

动画播放完成通知

<Image gif:ImageBehavior.RepeatBehavior="3x"
       gif:ImageBehavior.AnimatedSource="Images/animated.gif"
       gif:ImageBehavior.AnimationCompleted="AnimationCompleted"
/>
如果设置为无限重复播放,则不会引发此事件。

手动控制动画

在手动控制动画之前,最好先禁止 GIF 自动播放:
<Image Name="img"
       gif:ImageBehavior.AnimatedSource="animated.gif"
       gif:ImageBehavior.AutoStart="False"
/>
手动控制代码示例:
' 获取控制权限
Dim controller = ImageBehavior.GetAnimationController(img)
controller.Pause() '暂停
controller.Play() '播放
controller.GotoFrame(controller.FrameCount - 1) '跳到最后一帧

设置动画速度

下方示例为三倍速播放:
<Image Name="img" gif:ImageBehavior.AnimationSpeedRatio="3.0" />
ImageBehavior.SetAnimationSpeedRatio(img, 3.0)