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://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.



Comments