JokerMartini
JokerMartini

Reputation: 6147

wpf - improve speed of placing large image onto canvas

Is there a way in which I can improve the speed at which an insanely large image loads when placing it onto a canvas?

Is there a way I could use some sort of streaming method to load the image in chunks? Is there a way to stop the application from locking up when it's loading the image?

The image used for testing can be found here: http://www.finwe.mobi/orion360/test/equi/Orion360_test_image_8192x4096.jpg

The end result images will be larger than this.

Main.cs

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            ImageBrush ib = new ImageBrush();
            ib.ImageSource = new BitmapImage(new Uri(@"C:\Users\jmartini\Projects\wpf_image_streamer\testImage.png", UriKind.Relative));
            //mycanvas.Background = ib;
            canvas_view.Background = ib;
        }
    }
}

Main.XMAL

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Canvas Name="canvas_view"></Canvas>
    </Grid>
</Window>

Upvotes: 0

Views: 261

Answers (1)

RogerN
RogerN

Reputation: 3821

You'll need to load the image on a background thread to prevent your application from becoming unresponsive. You might consider displaying a lower-resolution version of the image at first so that the user has something to look at while the application loads the big version. You also need to consider displaying a progress bar, and which UI elements the user ought to be able to interact with while the image is still loading.

Although there are lots of things to consider when you start mixing asynchronous code with a user interface, the most basic use case is still relatively simple. The following example ought to get you started:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var brush = new ImageBrush(new BitmapImage(new Uri("thumbnail.jpg", UriKind.Relative)));
        canvas_view.Background = brush;
        this.Loaded += MainWindow_Loaded;
    }

    async void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        var bi = await LoadBigImage();
        canvas.Background = new ImageBrush(bi);
    }

    async Task<BitmapImage> LoadBigImage()
    {
        var bi = new BitmapImage(new Uri("fullsize.jpg", UriKind.Relative));
        bi.Freeze(); // note: must freeze DP objects when passing between threads
        return bi;
    }
}

Upvotes: 1

Related Questions