Search code examples
c#opencvuwpbackground-taskwriteablebitmap

UWP - How to use WriteableBimap in a background task? Alternative?


The following code reads an image, and centers (cuts and copies) that image into a resulting image with a black frame, returns the new image.

Can i do it without using a writeablebitmap class?

private async Task<WriteableBitmap> FrameToCenter(StorageFile image, Size newSize)
    {
        WriteableBitmap result = new WriteableBitmap((int) newSize.Width,(int) newSize.Height);

        WriteableBitmap bitmapToFrame = await StorageFileToSoftwareBitmap(image);

        Rect sourceRect = new Rect(0, 0, bitmapToFrame.PixelWidth, bitmapToFrame.PixelHeight);
        int a = (int) Math.Min(newSize.Height, newSize.Width);
        Rect destRect = new Rect((int) ((_screenResolution.Width - _screenResolution.Height)/2), 0, a, a);

        result.Blit(destRect, bitmapToFrame, sourceRect);

        return result;
    }

Everything worked fine, but then I tried to put that code into a BackgroundTask in UWP, that results in an exception due to the fact that I can not use WriteableBitmap on a different thread then the UI thread.

Is there anything else I can do? I need to run it in a backgroundtask though.

As well the line:

result.Blit(destRect, bitmapToFrame, sourceRect);

is actually using a WriteableBitmapEx extension which I won't be able to use. Any other way? I really dont see a way how to manipulate a bitmap on a background task thread. I am quiet lost here. I've been even thinking about using openCV library and just do it in C++, would that solve the problem?

There is as well this SO Q&A, which mentions I should derive my background task from XamlRenderingBackgroundTask class. How can I do that?


Solution

  • You use the XamlBackgroundTask the same way you would a regular BackgroundTask

    public sealed class MyBackgroundTask : XamlRenderingBackgroundTask
    {
        protected override async void OnRun(IBackgroundTaskInstance taskInstance)
        {
            var deferral = taskInstance.GetDeferral();
            //your code here
            deferral.Complete();
        }
     }
    

    The difference is that this will have access to the UI thread so you can use your WriteableBitmap.

    I would just keep an eye on the important recommendation in this article.

    Important To keep the memory footprint of the background task as low as possible, this task should be implemented in a C++ Windows Runtime Component for Windows Phone. The memory footprint will be higher if written in C# and will cause out of memory exceptions on low-memory devices which will terminate the background task. For more information on memory constraints, see Support your app with background tasks.