画像の表示

 画像ファイルを選択して表示する機能を作成してみます。単純に表示するだけではなく、大きな画像は拡大・縮小して表示できるようにします。

 まず画面を作成します。

  • 画面上部にファイル選択を実行するためのボタンを配置します。
  • その下に画像を表示するための Image を配置しますが、拡大・縮小のために ScrollViewer を配置し、その中に Image を配置する形にします。
<Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Button x:Name="PickButton" Grid.Row="0" Content="選択" VerticalAlignment="Top" Width="107" Click="PickButton_Click" Margin="10,10,0,0"/>
    <ScrollViewer x:Name="ScrollPanel" Grid.Row="1" Margin="10,10,10,10" Background="{StaticResource ControlForegroundBrush}" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" MaxZoomFactor="1">
        <Image x:Name="MainImage" Margin="0" Stretch="None" SizeChanged="MainImage_SizeChanged" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </ScrollViewer>
</Grid>

 実行するとこんな感じになります。


 続いて内部の処理を記述します。最初は選択ボタンが押された時のファイル選択処理です。

  • ファイル選択も非同期処理なのでメソッドの宣言に async を追加します。
  • ファイル選択用の FileOpenPicker のインスタンスを生成し、必要なプロパティを設定してから選択処理を呼び出します。
  • 選択されたファイルを指定して BitmapImage を生成し Image に設定します。
private async void PickButton_Click(object sender, RoutedEventArgs e)
{
    var fileOpenPicker = new FileOpenPicker();

    fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
    fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
    fileOpenPicker.FileTypeFilter.Add("*");

    StorageFile file = await fileOpenPicker.PickSingleFileAsync();
    if (file != null)
    {
        var bmp = new BitmapImage();
        bmp.SetSource(await file.OpenReadAsync());
        MainImage.Source = bmp;
    }
}

 この段階で画像は表示されるようになっていますが、画像を読み込んだ段階で Image のサイズは読み込んだ画像のサイズになっています。このため、ScrollViewer より大きい画像を読み込んだ場合は、画像の一部が表示が表示された状態になってしまいます。

 これを、最初は ScrollViewer のサイズに合わせて縮小して表示し、ユーザーの操作で拡大できるようにします。

  • Image のサイズは画像を設定した処理内ではまだサイズが変っていませんので、サイズが変った後のイベント内に処理を記述します。
  • 画像が ScrollViewer より小さい場合は拡大・縮小できないようにして、そのままピクセル等倍相当で表示します。
  • 大きい場合は ScrollViewer とほぼ同じサイズになる倍率を算出し、初期状態では算出した倍率で表示するようにします。
private void MainImage_SizeChanged(object sender, SizeChangedEventArgs e)
{
    if (e.NewSize.Width == 0.0 || e.NewSize.Height == 0.0)
    {
        return;
    }

    if (e.NewSize.Width > ScrollPanel.ViewportWidth || e.NewSize.Height > ScrollPanel.ViewportHeight)
    {
        // 画像の方がScrollViewerより大きい
        float horzZoomFactor = (float)(ScrollPanel.ViewportWidth / e.NewSize.Width);
        float vertZoomFactor = (float)(ScrollPanel.ViewportHeight / e.NewSize.Height);

        float zoomFactor = horzZoomFactor;
        if (zoomFactor > vertZoomFactor)
        {
            zoomFactor = vertZoomFactor;
        }

        ScrollPanel.MinZoomFactor = zoomFactor;
        ScrollPanel.ZoomToFactor(zoomFactor);
    }
    else
    {
        // 画像の方がScrollViewerより小さい
        ScrollPanel.MinZoomFactor = 1.0f;
        ScrollPanel.ZoomToFactor(1.0f);
    }
}

 これで終了です。ScrollViewer が拡大・縮小の機能を持っていますので、倍率を指定しておくだけで処理してくれます。

 それでは実行してみます。まず、選択ボタンを押した時の画面です。


 ここでファイルを選択すると、ピクセル等倍相当で表示されます。


 ピンチアウトして拡大もできます。


 タッチパネル付きのマシンがあればピンチイン・アウトして簡単に確認できますが、ない場合は代替操作で確認する事になります。

 単純なズームはCtrl+ホイールで実行できます。
 シミュレーターで実行している場合は、ピンチイン・アウトの機能があります。機能を選択するとタッチ位置のマークが二つ表示されますので、マウスをクリックしたままにしてホイールする事でズームできます。
 指がある場所を中心に拡大していく動作等を見たい場合はシミュレーターで確認する必要があります。