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


    在最近的项目中,遇到一个关于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.DecodePixelWidth = 800;
    
        image.EndInit();
    
        image.Freeze();
    
        models.Add(new ImageSourceModel() { ImageSource = image });

    此时的内存占用如图

    内存降低的非常显著,此时同样多的图片内存占用只有40M左右。

    最终我们可以把优化方案1和优化方案2结合起来。这样在加载多张图片时不会出现卡顿的现象。另外从用户体验的角度我们可以在图片显示出来前,先用一个Loading的动画效果过渡下。

    感谢您的阅读。代码和测试图片请点击这里下载。

  • 相关阅读:
    ubuntu重新安装mysql
    linux基本命令
    ubuntu启用root用户
    cada的常规使用
    如果有人对我的mysql的笔记感兴趣请联系我,互相学习
    10、mysql查看进程
    09、Mysql 查询是否锁表
    08、查看锁记录等待时间:
    针对发送网络附件的java方法(使用Apache的jar包调用)
    mysql的卸载重装+导入大量数据失败的解决方案+工具执行和项目执行结果不同
  • 原文地址:https://www.cnblogs.com/yang-fei/p/4931406.html
Copyright © 2020-2023  润新知