BattleProgrammerShibata

ある日は誰かと戦い、ある日は何かと戦い、そしてある日は自分と戦うのだろう、そういう生き物。

[WinRT][WinodwsPhone8.1] インターネット経由で取得して Image コントロールに表示している画像を保存する

Twitterソースコードを晒したらより冴えたやり方を雪猫さんが記事にしてくれた。

[WinRT] Image コントロールに表示している画像を保存するポップアップメニュー | 雪猫ノート

http://blog.snowcait.info/2015/09/25/winrt-popupmenu-to-save-image/

この記事を参考*1に以下のように実装した。
Image コントロールの Source から得た画像 URL で HTTP リクエストを掛け、それを保存している。

private async void SaveHoldingImage(Windows.UI.Xaml.Controls.Image image)
{
    var bmpImage = (BitmapImage)image.Source;
    var fileName = Path.GetFileName(bmpImage.UriSource.AbsolutePath);
    if (string.IsNullOrEmpty(fileName))
    {
        fileName = "AppName_dateTime";
    }

    var extension = Path.GetExtension(fileName);
    var client    = new Windows.Web.Http.Windows.Web.Http.HttpClient();
    var response  = await client.GetAsync(bmpImage.UriSource);
    if (string.IsNullOrEmpty(extension))
    {
        extension = response.Content.Headers.ContentType.MediaType.Replace("image/", ".");
    }
    var buffer = await response.Content.ReadAsBufferAsync();

    var imageFolder = await KnownFolders.PicturesLibrary.CreateFolderAsync("任意のフォルダ", CreationCollisionOption.OpenIfExists);
    var imageFile   = await imageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);

    await FileIO.WriteBufferAsync(imageFile, buffer);
}

↑を適用する前の実装

WindowsPhone 7 時代の遺産的なやつ。
こちらでは Image コントロールの画像を RenderTargetBitmap にぶち込み、その上 Jpeg 圧縮していた。

private async void SaveHoldingImage(Windows.UI.Xaml.Controls.Image image)
{
    var imageFolder        = await KnownFolders.PicturesLibrary.CreateFolderAsync("任意の名前", CreationCollisionOption.OpenIfExists);
    var renderTargetBitmap = new RenderTargetBitmap();
    await renderTargetBitmap.RenderAsync(image, (int)image.ActualWidth, (int)image.ActualHeight);
    var pixles    = (await renderTargetBitmap.GetPixelsAsync()).ToArray();
    var imageFile = await imageFolder.CreateFileAsync("任意のファイル名", CreationCollisionOption.ReplaceExisting);

    using (var fileStream = await imageFile.OpenAsync(FileAccessMode.ReadWrite))
    {
       var encorder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, fileStream);
       encorder.SetPixelData(
           BitmapPixelFormat.Bgra8,
           BitmapAlphaMode.Straight,
           (uint)renderTargetBitmap.PixelWidth,
           (uint)renderTargetBitmap.PixelHeight,
           DisplayInformation.GetForCurrentView().LogicalDpi,
           DisplayInformation.GetForCurrentView().LogicalDpi,
           pixles);
       await encorder.FlushAsync();
    }
}

*1:ほぼコピペ