WPFでGIF画像を簡単に表示するライブラリ「WPF Animated GIF」を使ってみた

# はじめに
本記事はWPFでGIF画像を簡単に表示するライブラリの WPF Animated GIF の使い方と便利に感じた点をまとめることを目的としています。

# WPF Animated GIFとは
WPFで画像を表示するためのコントロールであるImageコントロールでGIF画像を簡単に表示するためのライブラリです。
WPFではStoryBoardなどを使ってGIF画像のようなアニメーションを表示することはできますが、WPF Animated GIF を使うと既存のImageコントロールでGIF画像が表示できるようになります。
表示以外にもGIF画像の再生、一時停止、シーク(任意の位置から再生する機能)機能も実現可能です。
詳細は[WPF Animated GIFのGitHubページ](https://github.com/XamlAnimatedGif/WpfAnimatedGif)を参照ください。

# 使い方
WPF Animated GIFのインストール方法、WPF Animated GIFを使ってのGIF画像の表示、再生、一時停止、シーク機能の使い方をそれぞれ以下に示します。

## インストール方法
Visual StudioでdotNetCoreのWPFアプリケーション用プロジェクトを作成し、作成したプロジェクトを右クリックして、[NuGetパッケージの管理]メニューを実行します。
以下のWpfAnimatedGifをインストールすることで、利用準備は完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452292/0cb82431-4bfe-f7ed-0e7c-a36f7795cb33.png)

## GIF画像の表示
WPF Animated GIFは、ImageコントロールにGIF画像を表示するための機能をビヘイビアで提供しています。
WPFアプリケーションプロジェクトを作ると自動作成されるMainWindow.xamlを以下のように記載するだけでGif画像の表示が可能です。

- MainWindow.xaml

```xml
<!--WpfAnimatedGifの機能を提供する名前空間をgifという名前で読み込む-->
<Window x:Class="UsingWpfAnimatedGif.MainWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:gif="http://wpfanimatedgif.codeplex.com"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="350">
    <!-- プロジェクトに追加したGIF画像をパスで指定して表示 -->
    <!-- AutoStartプロパティをtrueにすることでGIF画像を自動再生するようにしている。 -->
    <Image gif:ImageBehavior.AnimatedSource="Resources/sample.gif"
           gif:ImageBehavior.AutoStart="True"/>
</Window>
```

- 実行したプログラム(表示しているGifは[こちら](http://katus-gifani.sakura.ne.jp/)のサイトのものです。)

![GIF画像表示サンプル.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452292/2d613f55-84f0-53f9-5054-c43227e5e81a.gif)

## GIF画像の再生
WPF Animated GIFによって提供されるImageコントロール用のビヘイビアの機能(ImageBehavior.AutoStartプロパティ)を使って、GIFの自動再生をしない設定にします。
そのうえで、再生ボタンによってGIF画像を再生するようにしてみます。
やり方は簡単です。まず、Imageコントロール用のビヘイビアが発行するAnimationLoadedイベントをハンドリングして、ハンドラ内でGIFを表示するImageコントロール用のGIF画像コントローラを取得し、内部プロパティで保持しておきます。次に再生ボタンのClickイベントをハンドリングして、そのハンドラ内で事前に保持していたImageコントロール用のGIF画像コントローラのPlayメソッドでGIF画像を再生します。
Imageコントロール用のビヘイビアが発行するAnimationLoadedイベントが発行されたタイミング以降でしか、Imageコントロール用のGIF画像コントローラは取得できないため注意が必要です。つまり、MainWindow.xaml.csのコンストラクタ内で`ImageBehavior.GetAnimationController`メソッドでImageコントロール用のGIF画像コントローラを取得しようとしても、そのタイミングではGIF画像の読み込みが終わっておらずAnimationLoadedイベントも発行されていないため、正常にコントローラが取得できません。
実際のMainWindow.xaml並びにMainWindow.xaml.csと実行したプログラムのイメージは以下です。

- MainWindow.xaml
```xml
<Window x:Class="UsingWpfAnimatedGif.MainWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:gif="http://wpfanimatedgif.codeplex.com"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="350">
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <!-- 再生ボタン -->
            <Button x:Name="_PlayButton" Click="_PlayButton_OnClick">再生</Button>
        </StackPanel>
        <!-- AutoStartプロパティをFalseにすることでGIF画像を自動再生しないようにしている。 -->
        <Image x:Name="_GitImage" DockPanel.Dock="Bottom"
               HorizontalAlignment="Left"
               gif:ImageBehavior.AutoStart="False"
               gif:ImageBehavior.AnimatedSource="Resources/sample.gif"
               gif:ImageBehavior.AnimationLoaded="_GitImage_OnAnimationLoaded"/>
    </DockPanel>
</Window>
```

- MainWindow.xaml.cs
```cs
using System.Windows;
using WpfAnimatedGif;

namespace UsingWpfAnimatedGif
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// Gif画像コントロール用のコントローラ
        /// </summary>
        private ImageAnimationController Controller { get; set; }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 再生ボタンクリック時のイベントハンドラ
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _PlayButton_OnClick(object sender, RoutedEventArgs e)
        {
            if (Controller == null) return;

            // Gif画像を再生
            Controller.Play();
        }

        /// <summary>
        /// Gif画像コントロールの読み込み後のイベントハンドラ
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _GitImage_OnAnimationLoaded(object sender, RoutedEventArgs e)
        {
            // Gif画像コントロール用のコントローラ取得
            Controller = ImageBehavior.GetAnimationController(_GitImage);
        }
    }
}
```

- 実行したプログラム

![GIF画像再生サンプル.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452292/98c3cc32-af65-1ffe-b688-b5edc8d3dd3d.gif)


## GIF画像の一時停止
前章のGIF画像の再生の時に取得して保持していたコントローラを使うことで一時停止も可能です。
一時停止用のボタンを追加して、そのボタンのClickイベントのハンドラ内でコントローラ経由でGIF画像を一時停止します。
実際のMainWindow.xaml並びにMainWindow.xaml.csと実行したプログラムのイメージは以下です。

- MainWindow.xaml
```xml
<Window x:Class="UsingWpfAnimatedGif.MainWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:gif="http://wpfanimatedgif.codeplex.com"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="350">
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <Button x:Name="_PlayButton" Click="_PlayButton_OnClick">再生</Button>
            <!-- 一時停止ボタン -->
            <Button x:Name="_PauseButton" Click="_PauseButton_OnClick">一時停止</Button>
        </StackPanel>
        <Image x:Name="_GitImage" DockPanel.Dock="Bottom"
               HorizontalAlignment="Left"
               gif:ImageBehavior.AutoStart="False"
               gif:ImageBehavior.AnimatedSource="Resources/sample.gif"
               gif:ImageBehavior.AnimationLoaded="_GitImage_OnAnimationLoaded"/>
    </DockPanel>
</Window>
```

- MainWindow.xaml.cs

```cs
using System.Windows;
using WpfAnimatedGif;

namespace UsingWpfAnimatedGif
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // 以下のハンドラを新たに追加

        /// <summary>
        /// 一時停止ボタンクリック時のイベントハンドラ
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _PauseButton_OnClick(object sender, RoutedEventArgs e)
        {
            if (Controller == null) return;

            // Gif画像を一時停止
            Controller.Pause();
        }
    }
}

```

- 実行したプログラム

![GIF画像再生・一時停止サンプル.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452292/0fd51529-83de-cd48-7afc-6521302f9dcb.gif)


# GIF画像のシーク
GIF画像のシーク機能の確認として、GIF画像の最初に戻すボタンを作ってみます。
最初に戻すボタンを追加して、ボタンをClickされた際のハンドラも追加します。ハンドラ内ではGotoFrameメソッドを使って指定したフレームにGIF画像の状態を戻します。ここでは最初に戻すため0フレーム目に戻しています。
なお、一時停止と同様にImageコントロール用のGIF画像コントローラを使って制御しています。

- MainWindow.xaml
```xml
<Window x:Class="UsingWpfAnimatedGif.MainWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:gif="http://wpfanimatedgif.codeplex.com"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="350">
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <Button x:Name="_PlayButton" Click="_PlayButton_OnClick">再生</Button>
            <Button x:Name="_PauseButton" Click="_PauseButton_OnClick">一時停止</Button>
            <!-- 最初に戻るボタン -->
            <Button x:Name="_ReturnStartButton" Click="_ReturnStartButton_OnClick">最初に戻る</Button>
        </StackPanel>
        <Image x:Name="_GitImage" DockPanel.Dock="Bottom"
               HorizontalAlignment="Left"
               gif:ImageBehavior.AutoStart="False"
               gif:ImageBehavior.AnimatedSource="Resources/sample.gif"
               gif:ImageBehavior.AnimationLoaded="_GitImage_OnAnimationLoaded"/>
    </DockPanel>
</Window>
```

- MainWindow.xaml.cs
```cs
using System.Windows;
using WpfAnimatedGif;

namespace UsingWpfAnimatedGif
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        // 以下のハンドラを新たに追加

        /// <summary>
        /// 最初に戻るボタンクリック時のイベントハンドラ
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _ReturnStartButton_OnClick(object sender, RoutedEventArgs e)
        {
            if (Controller == null) return;

            // Gif画像を最初に戻す
            // 0フレーム目に戻すことでGif画像を初めから再生できる
            Controller.GotoFrame(0);
        }
    }
}
```

- 実行したプログラム

![GIF画像最初に戻るサンプル.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452292/622cd8be-f8b5-d7a9-c676-9deae5f81cd9.gif)


# 便利だと思った点
ビヘイビアを使うことで元のIamgeコントロールと同じような使用感でGif画像を表示できるのが便利と感じました。加えてビヘイビアを使うことで再生・一時停止・シーク機能も簡単に実装できる点も便利だなと感じました。

# さいごに
WPFアプリケーションでGIF画像を表示するために便利な WPF Animated GIF の使い方と便利な点をまとめました。
この記事で紹介したのは基本機能だけですが、かなり便利だと思いました。手軽にGIF画像をWPFアプリケーションで表示したい場合には使ってみようと思います。