Speeding up image loading in WPF using thumbnails

Technorati Tags: wpfthumbnailsimageperformanceslowBitmapImage

During a recent WPF session I needed to build a ListBox that showed a bunch of images loaded from an arbitrary directory. Thanks to WPF‘s data binding, this was trivial - I just needed to get a collection of objects that each had a property pointing to the full path of the image, and WPF would take care of all the loading/displaying. Something like this:

   1: <ListView ItemsSource="{Binding}">
   2:     <ListView.ItemTemplate>
   3:         <DataTemplate>
   4:             <Image Source="{Binding Path=FullPath}" />
   5:         </DataTemplate>
   6:     </ListView.ItemTemplate>
   7: </ListView>

The assumption here is that the DataContext for this window is set to a collection of "Photo" objects. The Photo class has a member called "FullPath" which is just a string with the full path of the photo on disk - this is what the Image.Source member expects.

This worked, but it didn‘t take long to see a major issue: With today‘s cameras, loading multiple 5+ megapixel images could take a while (not to mention the RAM requirements).

After a little digging, I found a solution. There exists a feature in the BitmapImage class that allows you to load an image but tell it to only load a thumbnail. To use this, you have to step out of the shrink-wrapped data binding world and insert a converter into the equation. Basically, this converter will take the above string with the full image path, it will load the image (as a thumbnail), and pass it back into the Image.Source parameter as aBitmapImage, which it‘s happy to consume.

First, let‘s look at this converter‘s code and how it loads the thumbnail:

   1: public class UriToBitmapConverter : IValueConverter
   2: {
   3:     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   4:     {
   5:         BitmapImage bi = new BitmapImage();
   6:         bi.BeginInit();
   7:         bi.DecodePixelWidth = 100;
   8:         bi.CacheOption = BitmapCacheOption.OnLoad;
   9:         bi.UriSource = new Uri( value.ToString() );
  10:         bi.EndInit();
  11:         return bi;
  12:     }
  13:  
  14:     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  15:     {
  16:         throw new Exception("The method or operation is not implemented.");
  17:     }
  18: }

Notice line #7. That‘s the magic line which tells it how big of a thumbnail to load. The smaller the number, the quicker the load, the lower the quality. Notice also line #8 - this is there to force the image file to be closed after it‘s loaded. Without that, I found that my app couldn‘t write back to the image file since the ListBox still had it open.

Next, let‘s look at the XAML change to insert this converter into the mix. You‘ll need to create a resource for it:

   1: <Window.Resources>
   2:     <local:UriToBitmapConverter x:Key="UriToBitmapConverter" />
   3: </Window.Resources>

The "local:" namespace directive on line #2 is one I‘d made sure to add to my main "Window" declaration, like this (line #4):

   1: <Window x:Class="MyClass.Demo"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:local="clr-namespace:MyClass"
   5:     Title="Demo" Height="300" Width="300">

Lastly, use this new resource in the Image element so that FullPath (a string) gets pushed through the converter before Image.Source gets it:

   1: <Image Source="{Binding Path=FullPath, Converter={StaticResource UriToBitmapConverter}}" />

That‘s it. Your images will now load very quickly. Tweak the thumbnail size to vary the speed versus quality.

Avi

时间: 2024-08-09 02:52:02

Speeding up image loading in WPF using thumbnails的相关文章

awesome-qt

Awesome Qt  A curated list of awesome tools, libraries, and resources for the Qt framework. Qt is a powerful cross-platform application development framework, for use primarily (but not exclusively) in C++. It's great for GUI applications, but can be

jar命令使用介绍

http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/jar.html Skip to Content Oracle Technology Network Software Downloads Documentation Search jar-The Java Archive Tool jar combines multiple files into a single JAR archive file. Synopsis Des

WPF/SL: lazy loading TreeView

Posted on January 25, 2012 by Matthieu MEZIL 01/26/2012: Code update Imagine the following scenario: you have a WCF service with two methods: List<Customer> GetCustomers(); List<Order> GetOrders(int CustomerId); You want a treeview with lazy l

WPF动画 - Loading加载动画

存在问题: 最近接手公司一个比较成熟的产品项目开发(WPF桌面端),其中,在登陆系统加载时,60张图片切换,实现loading闪烁加载,快有密集恐惧症了!!! 代码如下: private void LoadPics() { try { _storyboard = new Storyboard(); for (int i = 0; i < 60; i++) { ObjectAnimationUsingKeyFrames oauf = new ObjectAnimationUsingKeyFrame

WPF实现炫酷Loading控件

Win8系统的Loading效果还是很不错的,网上也有人用CSS3等技术实现,研究了一下,并打算用WPF自定义一个Loading控件实现类似的效果,并可以让用户对Loading的颗粒(Particle)背景颜色进行自定义,话不多说,直接上代码: 1.用VS2012新建一个WPF的用户控件库项目WpfControlLibraryDemo,VS自动生成如下结构: 2.删除UserControl1.xaml,并新建一个Loading的CustomControl(不是UserControl),如下图所示

WPF loading加载动画库

原文:WPF loading加载动画库 1. 下载Dll ?????? https://pan.baidu.com/s/1wKgv5_Q8phWo5CrXWlB9dA 2.在项目中添加引用 ??????? 略 3.在Xaml中引入名称空间 ????? xmlns:myLib="clr-namespace:MyLoadingLib;assembly=MyLoadingLib" 4.使用代码 ?????<StackPanel>???? <myLib:CirclePoint

WPF 客户端浏览器 添加Loading加载进度

原文:WPF 客户端浏览器 添加Loading加载进度 在windows开发界面时,使用浏览器来请求和显示网页内容,是比较常见的. 但是在请求网页内容时,因网速或者前端功能复杂加载较慢,亦或者加载时遇到各种问题,如空白/黑屏/加载不完整/证书问题等. 因此需要一个加载进度/加载失败的显示界面. 加载进度显示 界面显示 1. 界面显示,加载进度样式可参考: 绕圈进度条 2. 添加Loading状态枚举.不加载/加载中/加载失败 1 public enum LoadingState 2 { 3 No

WPF和Expression Blend开发实例:Loading动画

今天来点实际的,项目中可以真实使用的,一个Loading的动画,最后封装成一个控件,可以直接使用在项目中,先上图: 整个设计比较简单,就是在界面上画18个Path,然后通过动画改变OpacityMask的值来实现一种动态的效果. 因为整个过程比较简单,所以其实没有用到Blend,唯一一个需要注意的是Path的路径值是请美工从PS里生成的,路径如下: <Geometry x:Key="Block"> M291.15499,85.897525 C291.15499,85.897

WPF loading遮罩层 LoadingMask

先上张效果图看看 如果不如您的法眼 可以移步了 或者有更好的效果 可以留言给我 废话不多说 直接贴代码 一个usercontrol <UserControl x:Class="LoadingMask_Demo.LoadingWait" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx