Search code examples
c#windows-store-appswinrt-asyncwriteablebitmapex

Async Image editing with WriteableBitmapEx


I'm currently writing a small Image editing app for the Windows Store (WinRT) using the great WriteableBitmapEx Framework. As functions like .convolute can take a while on WinRT devices (tested on Surface) I'd like to make those requests async so the UI doesn't get blocked and I can show a progress ring.

This is what I've tried so far, an the code itself is working. But the UI still gets blocked and the ring does not show. The code does take about 2 seconds to execute.

// Start Image editing when selection is changed
private async void FilterListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        progressRing.IsActive = true;

        try
        {
            filteredImage = await FilterMethod.imageBW(originalImage, filteredImage);

        }
        catch
        {
            Debug.WriteLine("No items selected");
        }

        mainImage.Source = filteredImage;
        progressRing.IsActive = false;
    }


    // Black & White
    public static async Task<WriteableBitmap> imageBW(WriteableBitmap originalImage, WriteableBitmap filteredImage)
    {
        filteredImage = originalImage.Clone();

        using (filteredImage.GetBitmapContext())
        {
            filteredImage.ForEach(ImageEdit.toGrayscale);
        }

        return filteredImage;
    }


    // Grayscale
    public static Color toGrayscale(int x, int y, Color color)
    {
        byte gray = (byte)(color.R * .3f + color.G * .59f + color.B * .11f);
        Color newColor = Color.FromArgb(255, gray, gray, gray);
        return newColor;
    }

Solution

  • As this kind of image editing seems to be needing to happen on the UI thread, I was able to wrap my code inside a

    await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {}
    

    block, so now it looks like this:

    private async void FilterListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        progressRing.IsActive = true;
    
        try
        {
            await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                filteredImage = await FilterMethod.imageBW(originalImage, filteredImage);
            }
    
        }
        catch
        {
            Debug.WriteLine("No items selected");
        }
    
        mainImage.Source = filteredImage;
        progressRing.IsActive = false;
    }