I'm trying to write a little photo viewer in WPF, basically emulating what Windows Photo Viewer is offering.
Displaying in both windowed and fullscreen mode is done using an Image
<Image Name="ImgDisplay" Source="{Binding CurrentImage.FullPath, Converter={StaticResource FilenameToImageConverter}}"/>
where the FilenameToImageConverter
does the following
public class FilenameToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string uri = value as string;
if (uri != null && File.Exists(uri))
{
BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.None;
image.UriCachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.BypassCache);
image.CacheOption = BitmapCacheOption.OnLoad;
image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
image.UriSource = new Uri(uri);
image.EndInit();
return image;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
When testing the program with my photos however (around 8mpx, 4MB jpeg files), the load times for displaying the images are huge (2 or 3 seconds), while Windows Photo Viewer is able to skip through the images with ease. I see it first displaying a lower-resolution version of the image, shortly before displaying the full one. Everything however ends up way faster than my approach.
How can I achieve this? Is it all through thumbnails/preloading? Thank you in advance
Edit
Thanks, the tips given, scaling down using DecodePixelWidth
as well as Async/OneWay-Bindings have improved the situation substantially, though not enough to make everything fluent. Also with IsAsync=true
, the image will always be blank before loading the next image, which is an unpleasant effect.
It would be nice to solve that through displaying a highly downscaled version immediately and afterwards display the full image when it has been loaded asynchronously. As there is some sort of temporal succession involved, I have no idea how to implement that with bindings. Any suggestions, please?