Skip to content

Commit

Permalink
Make PlatformBitmapLoader work on any thread on WinRT
Browse files Browse the repository at this point in the history
Microsoft owes me a medal for the nonsense I put up with on these silly goose
platforms
  • Loading branch information
anaisbetts committed Oct 14, 2013
1 parent 5819802 commit ca13a2c
Showing 1 changed file with 60 additions and 35 deletions.
95 changes: 60 additions & 35 deletions Splat/WinRT/Bitmaps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,58 +10,64 @@
using Windows.Storage.Streams;
using Windows.UI.Xaml.Media.Imaging;
using Windows.Storage;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;

namespace Splat
{
class PlatformBitmapLoader : IBitmapLoader
{
public async Task<IBitmap> Load(Stream sourceStream, float? desiredWidth, float? desiredHeight)
{
using (var rwStream = new InMemoryRandomAccessStream()) {
await sourceStream.CopyToAsync(rwStream.AsStreamForWrite());

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;
return await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(async () => {
using (var rwStream = new InMemoryRandomAccessStream()) {
await sourceStream.CopyToAsync(rwStream.AsStreamForWrite());

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;
}
}
}

if (tryFallback) {
return await new FallbackBitmapLoader().Load(sourceStream, desiredWidth, desiredHeight);
}
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 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 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);
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<IBitmap> 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)
Expand Down Expand Up @@ -159,4 +165,23 @@ public static BitmapSource ToNative(this IBitmap This)
}
}

static class DispatcherMixin
{
public static Task<T> RunAsync<T>(this CoreDispatcher This, Func<Task<T>> func, CoreDispatcherPriority prio = CoreDispatcherPriority.Normal)
{
var tcs = new TaskCompletionSource<T>();

This.RunAsync(prio, () => {
func().ContinueWith(t => {
if (t.IsFaulted) {
tcs.SetException(t.Exception);
} else {
tcs.SetResult(t.Result);
}
});
});

return tcs.Task;
}
}
}

0 comments on commit ca13a2c

Please sign in to comment.