Victoria L.
Victoria L.

Reputation: 61

Load an Image to a Canvas Control from a File Picker

What I'm trying to do in a UWP app with Win2D: User pressed a button to add an image and picks their file. That file gets loaded as a resource for a Canvas Control. The image then gets rendered to the current drawing session

When the button is clicked:

private async void btnAddPicture_Click(object sender, RoutedEventArgs e)
    {
        var picker = new Windows.Storage.Pickers.FileOpenPicker();
        picker.FileTypeFilter.Add(".png");
        picker.FileTypeFilter.Add(".jpg");
        picker.FileTypeFilter.Add(".jpeg");
        overlayPictureFile = await picker.PickSingleFileAsync();
        if (overlayPictureFile == null)
        {
            txbNotification.Text = "File Picking cancelled";
            return;
        }
        else
        {
            txbNotification.Text = "Picture Loaded";
        }
        using (IRandomAccessStream stream = await overlayPictureFile.OpenAsync(FileAccessMode.Read))
        {
            var device = new CanvasDevice();
            createdBitmap = await CanvasBitmap.LoadAsync(device, stream);
        }
    }

In the drawing function:

void CanvasControl_Draw(CanvasControl sender, CanvasDrawEventArgs args)
    {
        if (createdBitmap != null)
        {
            args.DrawingSession.DrawImage(createdBitmap, Drawing.FindDefaultRect());
        }
        drawingCanvas.Invalidate();
    }

Everything will compile but the moment I press the button to add an image it breaks here.

#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
        UnhandledException += (sender, e) =>
        {
            if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
        };

#endif

I'm already loading some image in this, but those are all part of the program and are created before the canvas is created with these. Not sure how to do that with ones the user picks.

private void drawingCanvas_CreateResources(CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
    {
        args.TrackAsyncAction(CreateResourcesAsync(sender).AsAsyncAction());
    }
    private async Task CreateResourcesAsync(CanvasControl sender)
    {
        logo = await CanvasBitmap.LoadAsync(sender, new Uri("ms-appx:///Assets/Pictures/Logo_BlackBorders.png"));
    }

Update: Where I currently am drawing things. This is the canvas I'm trying to add the image to.

void CanvasControl_Draw(CanvasControl sender, CanvasDrawEventArgs args)
    {
        //Drawing a bunch of stuff
    }
    private void drawingCanvas_CreateResources(CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
    {
        args.TrackAsyncAction(CreateResourcesAsync(sender).AsAsyncAction());
    }
    private async Task CreateResourcesAsync(CanvasControl sender)
    {
        logo = await CanvasBitmap.LoadAsync(sender, new Uri("ms-appx:///Assets/Pictures/Logo.png"));
    }

Upvotes: 1

Views: 604

Answers (1)

Nico Zhu
Nico Zhu

Reputation: 32775

Load an Image to a Canvas Control from a File Picker

For your scenario, you could get CanvasDrawingSession with CreateDrawingSession method. And then use this drawingsession to draw picked image to current CanvasControl.

For example.

private async void btnAddPicture_Click(object sender, RoutedEventArgs e)
{
    var picker = new Windows.Storage.Pickers.FileOpenPicker();
    picker.FileTypeFilter.Add(".png");
    picker.FileTypeFilter.Add(".jpg");
    picker.FileTypeFilter.Add(".jpeg");
    var overlayPictureFile = await picker.PickSingleFileAsync();
    if (overlayPictureFile == null)
    {

        return;
    }
    else
    {

    }
    using (IRandomAccessStream stream = await overlayPictureFile.OpenAsync(FileAccessMode.Read))
    {
        //get canvascontrol's Device property.
        CanvasDevice device = drawingCanvas.Device;
        createdBitmap = await CanvasBitmap.LoadAsync(device, stream);
        //use device property to make renderer
        var renderer = new CanvasRenderTarget(device,
                              createdBitmap.SizeInPixels.Width,
                              createdBitmap.SizeInPixels.Height, createdBitmap.Dpi);
        //make ds with above renderer.
        using (var ds = renderer.CreateDrawingSession())
        {
            ds.DrawImage(createdBitmap, 0, 0);
        }

    }
}

Upvotes: 1

Related Questions