[win8.1] RenderTargetBitmapクラスで、XAMLをビットマップ形式で保存する

WPFには RenderTargetBitmap クラスがあって、XAMLの要素を指定して画像を保存できたのですが、なぜか Windows 8 ではできませんでした。が、Windows 8.1 になって、これが導入されたのでストアアプリでお絵かきツールが作れますよ。ってのが、今回の変更で一番大きいかと…いや、そういう方もいらっしゃると思います。

XAML render to bitmap sample (Windows 8.1)
http://code.msdn.microsoft.com/windowsapps/XAML-render-to-bitmap-dd4f549f

をダウンロードすると、動的に矩形を追加させた後 grid を保存できます。
あれこれと、ごちゃごちゃしたサンプルなので、ばっさりと削ってしまってあらかじめ Canvas に Image やら TextBlock やらを貼り付けておいて、PNG形式で保存するソースが以下です。

private async void Button_Click(object sender, RoutedEventArgs e)
{
    // Render to an image at the current system scale and retrieve pixel contents
    RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
    await renderTargetBitmap.RenderAsync(this.panel);
    var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();

    var savePicker = new FileSavePicker();
    savePicker.DefaultFileExtension = ".png";
    savePicker.FileTypeChoices.Add(".png", new List<string> { ".png" });
    savePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
    savePicker.SuggestedFileName = "snapshot.png";

    // Prompt the user to select a file
    var saveFile = await savePicker.PickSaveFileAsync();

    // Verify the user selected a file
    if (saveFile == null)
        return;

    // Encode the image to the selected file on disk
    using (var fileStream = await saveFile.OpenAsync(FileAccessMode.ReadWrite))
    {
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, fileStream);

        encoder.SetPixelData(
            BitmapPixelFormat.Bgra8,
            BitmapAlphaMode.Ignore,
            (uint)renderTargetBitmap.PixelWidth,
            (uint)renderTargetBitmap.PixelHeight,
            DisplayInformation.GetForCurrentView().LogicalDpi,
            DisplayInformation.GetForCurrentView().LogicalDpi,
            pixelBuffer.ToArray());

        await encoder.FlushAsync();
    }
}

サンプルより抜粋…というか、そのままですね。RenderTargetBitmap クラスの RenderAsync メソッドで XAML 要素からレンダリングの画像データを取ってきて、GetPixelsAsync メソッドで byte 配列にします。実に簡単。。必要な namespace は、適宜 VS2013 preview を使って加えてください。

デザイン時に以下のように画像を貼り付けます。Opacity で半透明にしたりとか色々。回転させても大丈夫です。

実行時

そして、Save ボタンを押して保存した結果

バカバカしいほど簡単にできます…つーか、これが Windows 8 で実装されていなかったのが不思議なぐらい。
ちなみに画面の外に出てしまった時はどうなるのか?というと、大丈夫です。きちんと RenderTargetBitmap が対象にしている XAML 配下をきちんとレンダリングしてくれているので、はみ出た分も画像ファイルとして保存されます。
これでストア版のお絵かきツール作成がはかどりますね。

サンプルのダウンロードは以下からどうぞ
PanelToBitmap-v0.1.zip
http://sdrv.ms/1aEOZeu

カテゴリー: C#, WinRT パーマリンク