かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

UWPで画像に文字を描いたりする

画像を表示するだけなら簡単なんですが、これに文字を描いたりとかするとなるとちょっとめんどうになります。 Win2D使うとお手軽にできるらしいので挑戦。

NuGetでWin2Dで検索してWin2D.uwpをインストールします。

XAMLに以下のようにCanvasControlを追加します。

<Page x:Class="App38.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App38"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
      mc:Ignorable="d"
      Unloaded="Page_Unloaded">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ScrollViewer HorizontalScrollBarVisibility="Auto"
                      VerticalScrollBarVisibility="Auto">
            <canvas:CanvasControl x:Name="Canvas" Draw="CanvasControl_Draw" />
        </ScrollViewer>
    </Grid>
    <Page.BottomAppBar>
        <CommandBar>
            <AppBarButton Content="Load"
                          Click="LoadButton_Click" />
        </CommandBar>
    </Page.BottomAppBar>
</Page>

そして、LoadButton_Clickで以下のように画像を読み込む処理を書きます。

private CanvasBitmap Image { get; set; }

private async void LoadButton_Click(object sender, RoutedEventArgs e)
{
    var picker = new FileOpenPicker();
    picker.FileTypeFilter.Add(".jpg");
    picker.FileTypeFilter.Add(".jpeg");
    picker.FileTypeFilter.Add(".png");
    var file = await picker.PickSingleFileAsync();
    if (file == null) { return; }

    using (var s = await file.OpenReadAsync())
    {
        this.Image = await CanvasBitmap.LoadAsync(this.Canvas, s);
    }
    this.Canvas.Invalidate();
}

CanvasControlのDrawイベントでイメージを描画して、文字を書き込みます。ここらへんの細かいメソッドはWin2Dの公式サイトとかぐぐって見つけるのがよさそう。

Introduction

private void CanvasControl_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
    if (this.Image != null)
    {
        args.DrawingSession.DrawImage(this.Image);
        this.Canvas.Width = this.Image.Bounds.Width;
        this.Canvas.Height = this.Image.Bounds.Height;

        args.DrawingSession.DrawText(
            "Hello world",
            new System.Numerics.Vector2(10, 10),
            Colors.Red);
    }
}

後は、後始末を忘れないようにしないといけません。

private void Page_Unloaded(object sender, RoutedEventArgs e)
{
    this.Canvas.RemoveFromVisualTree();
    this.Canvas = null;
}

実行して画像を選択するとこんな感じになります。

f:id:okazuki:20160228212008p:plain