かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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