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:ほぼコピペ