Thumbnail Solutions

So based on last nights performance troubles loading thumbnail images I spent a couple of minutes “googling” and discovered the following useful links:

http://blogs.msdn.com/dditweb/archive/2007/08/22/speeding-up-image-loading-in-wpf-using-thumbnails.aspx

http://msdn2.microsoft.com/en-us/library/system.windows.media.imaging.bitmapframe_members.aspx

I tried the solution in the first link which involved creating a converter to use so that binding to a URI can result in a BitmapSource that uses the DecodePixelWidth/Height property.

    public class UriToBitmapConverter : IValueConverter
    {
public UriToBitmapConverter()
{
DecodeResolution = 100;
}
public int DecodeResolution { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.DecodePixelWidth = DecodeResolution;
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.UriSource = new Uri( value.ToString() );
bi.EndInit();
return bi;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}

This converter is then hooked up in the XAML something like as follows.

<Window x:Class="ThumbnailLoading.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ThumbnailLoading"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <local:PhotoCollection x:Key="photos" x:Name="photos"/>
        <local:UriToBitmapConverter x:Key="uriToBitmapConverter" DecodeResolution="60"/>
    </Window.Resources>
    <StackPanel>
        <ListView ItemsSource="{StaticResource photos}">
             <ListView.ItemTemplate>
                <DataTemplate>
                    <Image Width="60" 
Source
="{Binding Path=Uri, Converter={StaticResource uriToBitmapConverter}}"/> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackPanel> </Window>

Whilst this is an improvement as I suggested in the previous post from the folks at DDITDev – it is still too slow.

So I spent some time reading the MSDN documentation. The BitmapFrame class seemed to have a lot of cool functionality – including the ability to access image metadata. They even have properties for the commonly used properties such as Camera Model and Rating – very nice! However, of most interest was the Thumbnail property which suggested that it would return the thumbnail stored with the image. I used the Binding converter idea and created my own converter as follows.

    public class UriToThumbnailConverter : IValueConverter
    {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BitmapFrame bi = BitmapFrame.Create(new Uri(value.ToString()), 
BitmapCreateOptions.DelayCreation,
BitmapCacheOption.OnDemand); return bi.Thumbnail; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new Exception("The method or operation is not implemented."); } }

Then made the following changes to the XAML to declare and use the new binding converter.

<local:UriToThumbnailConverter x:Key=”uriToThumbnailConverter”/>

<Image Width=”60″ Source=”{Binding Path=Uri, Converter={StaticResource uriToThumbnailConverter}}”/>

This actually seemed to do the trick. I provided some statistics below which show the performance benefits. Of course in reality – as with PhotoPlay – any expensive image loading would normally happen on a background thread so maybe the binding converter isn’t really the best way to manage this.

  Bind direct to Uri Bind to Uri using DecodePixelWidth Bind to Uri using embedded Thumbnail
Loading 301 approx 280kb (1.1 megapixel) images 1 minutes
1.2 Gb
30 seconds
120 Mb
4 seconds
180 Mb
Loading 1102 approx 2Mb (5 megapixel) images Yeah right! 4 minutes 35 seconds
201 Mb
14 seconds
310 Mb

Note that the DecodePixel width method using the UriToBitmapConverter actually uses less memory because the embedded Thumbnails are actually bigger that the decode width of 60 pixels that I specified.

I also found this Microsoft sample application WPF Photo Viewer Demo which shows how Thumbnails and metadata can be extracted from digital photos.

3 thoughts on “Thumbnail Solutions”

Comments are closed.