From ca13a2c842649052fe4698c92dca74c67a28176e Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 14 Oct 2013 14:34:01 -0700 Subject: [PATCH] Make PlatformBitmapLoader work on any thread on WinRT Microsoft owes me a medal for the nonsense I put up with on these silly goose platforms --- Splat/WinRT/Bitmaps.cs | 99 ++++++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 37 deletions(-) diff --git a/Splat/WinRT/Bitmaps.cs b/Splat/WinRT/Bitmaps.cs index 210a6f8..065edcb 100644 --- a/Splat/WinRT/Bitmaps.cs +++ b/Splat/WinRT/Bitmaps.cs @@ -10,6 +10,8 @@ using Windows.Graphics.Imaging; using Windows.Storage.Streams; using Windows.UI.Xaml.Media.Imaging; using Windows.Storage; +using Windows.ApplicationModel.Core; +using Windows.UI.Core; namespace Splat { @@ -17,51 +19,55 @@ namespace Splat { public async Task Load(Stream sourceStream, float? desiredWidth, float? desiredHeight) { - using (var rwStream = new InMemoryRandomAccessStream()) { - await sourceStream.CopyToAsync(rwStream.AsStreamForWrite()); + return await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(async () => { + using (var rwStream = new InMemoryRandomAccessStream()) { + await sourceStream.CopyToAsync(rwStream.AsStreamForWrite()); - var decoder = default(BitmapDecoder); + var decoder = default(BitmapDecoder); - bool tryFallback = false; - try { - decoder = await BitmapDecoder.CreateAsync(rwStream); - } catch (Exception ex) { - if (ex.Message.Contains("0x88982F50") || ex.Message.Contains("0x88982F60")) { - // NB: Can't await in a catch block, have to do some silliness - tryFallback = true; - } else { - throw; + bool tryFallback = false; + try { + decoder = await BitmapDecoder.CreateAsync(rwStream); + } catch (Exception ex) { + if (ex.Message.Contains("0x88982F50") || ex.Message.Contains("0x88982F60")) { + // NB: Can't await in a catch block, have to do some silliness + tryFallback = true; + } else { + throw; + } + } + + if (tryFallback) { + return await new FallbackBitmapLoader().Load(sourceStream, desiredWidth, desiredHeight); + } + + var transform = new BitmapTransform(); + if (desiredWidth != null) { + transform.ScaledWidth = (uint)desiredWidth; + transform.ScaledHeight = (uint)desiredHeight; + } + + var pixelData = await decoder.GetPixelDataAsync(decoder.BitmapPixelFormat, decoder.BitmapAlphaMode, transform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.ColorManageToSRgb); + var pixels = pixelData.DetachPixelData(); + + var bmp = new WriteableBitmap((int)decoder.OrientedPixelWidth, (int)decoder.OrientedPixelHeight); + using (var bmpStream = bmp.PixelBuffer.AsStream()) { + bmpStream.Seek(0, SeekOrigin.Begin); + bmpStream.Write(pixels, 0, (int)bmpStream.Length); + return (IBitmap) new WriteableBitmapImageBitmap(bmp); } } - - if (tryFallback) { - return await new FallbackBitmapLoader().Load(sourceStream, desiredWidth, desiredHeight); - } - - var transform = new BitmapTransform(); - if (desiredWidth != null) { - transform.ScaledWidth = (uint)desiredWidth; - transform.ScaledHeight = (uint)desiredHeight; - } - - var pixelData = await decoder.GetPixelDataAsync(decoder.BitmapPixelFormat, decoder.BitmapAlphaMode, transform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.ColorManageToSRgb); - var pixels = pixelData.DetachPixelData(); - - var bmp = new WriteableBitmap((int)decoder.OrientedPixelWidth, (int)decoder.OrientedPixelHeight); - using (var bmpStream = bmp.PixelBuffer.AsStream()) { - bmpStream.Seek(0, SeekOrigin.Begin); - bmpStream.Write(pixels, 0, (int)bmpStream.Length); - return (IBitmap) new WriteableBitmapImageBitmap(bmp); - } - } + }); } public async Task LoadFromResource(string resource, float? desiredWidth, float? desiredHeight) { - var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(resource)); - using (var stream = await file.OpenAsync(FileAccessMode.Read)) { - return await Load(stream.AsStreamForRead(), desiredWidth, desiredHeight); - } + return await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(async () => { + var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(resource)); + using (var stream = await file.OpenAsync(FileAccessMode.Read)) { + return await Load(stream.AsStreamForRead(), desiredWidth, desiredHeight); + } + }); } public IBitmap Create(float width, float height) @@ -159,4 +165,23 @@ namespace Splat } } + static class DispatcherMixin + { + public static Task RunAsync(this CoreDispatcher This, Func> func, CoreDispatcherPriority prio = CoreDispatcherPriority.Normal) + { + var tcs = new TaskCompletionSource(); + + This.RunAsync(prio, () => { + func().ContinueWith(t => { + if (t.IsFaulted) { + tcs.SetException(t.Exception); + } else { + tcs.SetResult(t.Result); + } + }); + }); + + return tcs.Task; + } + } }