您的位置:首页 > 其它

WPF中加载高分辨率图片性能优化

2018-03-01 14:41 1086 查看
在最近的项目中,遇到一个关于WPF中同时加载多张图片时,内存占用非常高的问题。
问题背景:
在一个ListView中同时加载多张图片,注意:我们需要加载的图片分辨率非常高。
代码:
XAML:

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<Button Content="Load" Width="100" Height="35" Margin="0,10" Click="Button_Click"/>

<ListView Grid.Row="1" x:Name="lvImages">
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding ImageSource}" MaxWidth="800"/>
</DataTemplate>
</ListView.ItemTemplate>

<ListView.Template>
<ControlTemplate>
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden">
<ItemsPresenter />
</ScrollViewer>
</Grid>
</ControlTemplate>
</ListView.Template>

<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True" VirtualizingPanel.VirtualizationMode="Recycling" VirtualizingPanel.IsVirtualizing="True"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</Grid>

C#:

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

private void Button_Click(object sender, RoutedEventArgs e)
{
lvImages.Items.Clear();

// Image folder location: D:\Pics

string[] files = System.IO.Directory.GetFiles(@"D:\Pics");

List<ImageSourceModel> models = new List<ImageSourceModel>();

foreach(var path in files)
{
BitmapImage image = new BitmapImage();

image.BeginInit();

image.UriSource = new System.Uri(path);

image.EndInit();

image.Freeze();

models.Add(new ImageSourceModel() { ImageSource = image });
}

lvImages.ItemsSource = models;
}
}

public class ImageSourceModel
{
public ImageSource ImageSource { get; set; }
}

内存占用情况(此时只加载了20张图片,内存占用>1G):



优化方案:
1. 初始加载时,只加载部分图片并显示。当ScrollViewer滚动到底部时,再加载一部分。关于这个方案,可以参考 WPF MVVM模式下实现ListView下拉显示更多内容
但是这并不能解决最终内存占用过高的情况。
2. 给图片设置DecodePixelWidth属性,

BitmapImage image = new BitmapImage();

image.BeginInit();

image.UriSource = new System.Uri(path);

image.
b996
DecodePixelWidth = 800;

image.EndInit();

image.Freeze();

models.Add(new ImageSourceModel() { ImageSource = image });

此时的内存占用如图



内存降低的非常显著,此时同样多的图片内存占用只有40M左右。
最终我们可以把优化方案1和优化方案2结合起来。这样在加载多张图片时不会出现卡顿的现象。另外从用户体验的角度我们可以在图片显示出来前,先用一个Loading的动画效果过渡下。
感谢您的阅读。代码和测试图片请点击这里下载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: