跟图片打交道的 UWP 应用或多或少都会遇到图片带来的性能问题,就算不主要处理图片,做个论坛做个新闻客户端都涉及到大量图片。一个帖子、一篇文章里多半都是些高清大图,这些图片一张即可占用程序 1~2M 的内存空间。普通的写法内存很快就爆了,那么 UWP 中我们可以用哪些方法优化呢?


1. DecodePixelWidth/DecodePixelHeight

对于那些高分辨率图像,直接设置其 DecodePixelWidthDecodePixelHeight 的值为较小的值即可大大节省内存空间。以下两种方法中,后者对内存空间的节省非常显著。

<!-- 性能不好 -->
<Image Source="ms-appx:///Assets/high-resolution-image.jpg"
Width="300" Height="200"/>
<!-- 性能不错 -->
<Image>
<Image.Source>
<BitmapImage UriSource="ms-appx:///Assets/high-resolution-image.jpg"
DecodePixelWidth="300" DecodePixelHeight="200"/>
</Image.Source>
</Image>

2. 利用好自带的布局机制

如果没有指定 DecodePixelWidth/DecodePixelHeight,那么 XAML 会根据布局自动调整图片的解码大小。

不过,微软才不会让你这么开心地就用!如果你做了这些事,就当布局自带的内存优化不存在好了:

  1. 你先调了 SetSourceAsync 或设置了 UriSource,然后才把 BitmapImage 连接到活动的 XAML 树
  2. 使用异步解码(如 SetSource)解码图像。
  3. 把图像或父控件的 Opacity 设成了 0,或者 Visibility 设为 Collapsed
  4. ImageBrushStrech 设成了 None
  5. 图像用作点九图(参见 NineGrid
  6. 给图像或父控件设置了 CacheMode="BitmapCache"
  7. ImageBrush 绘制到不是矩形的地方 (试过画到文字上或形状上吗?)

关于第 1 条,这里有一些官方的代码作为例子:

<!-- 推荐写法,直接在 XAML 里指定 UriSoruce -->
<Image x:Name="myImage" UriSource="Assets/cool-image.png"/>
<!-- 但如果没有在 XAML 中指定,也可以去后台代码指定。 -->
<Image x:Name="myImage"/>
// 后台代码如果这样写就不错,因为先把 BitmapImage 放到了活动的 XAML 树上。
var bitmapImage = new BitmapImage();
myImage.Source = bitmapImage;
bitmapImage.UriSource = new URI("ms-appx:///Assets/cool-image.png", UriKind.RelativeOrAbsolute);
// 然而这样写就不太推荐了,因为先设置了 UriSource,再把 BitmapImage 放到活动的 XAML 树上。
var bitmapImage = new BitmapImage();
bitmapImage.UriSource = new URI("ms-appx:///Assets/cool-image.png", UriKind.RelativeOrAbsolute);
myImage.Source = bitmapImage;

3. 利用好自带的缓存机制

如果你用 UriSource 属性,那么恭喜,你将获得自带的图片缓存!如果多次使用相同的 Uri,那么会共用同一份内存空间。除此之外就没啦,比如自己创建一个流啊什么的;这就是说并不建议自己用 FileStream

另外,微软提供了这么好用的 SetSourceAsync,但是用了这个就没有缓存了!于是我到底是用还是不用呢?

4. GetThumbnailAsync

如果你使用本机文件,那么恭喜,你直接获得了拿到系统自带缩略图的机会!

使用系统自带的缩略图比前面的方法都更好,因为如果系统已经生成好了缩略图,你根本连解码图像都不需要。

FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".bmp");
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary; StorageFile file = await picker.PickSingleFileAsync(); StorageItemThumbnail fileThumbnail = await file.GetThumbnailAsync(ThumbnailMode.SingleItem, 64); BitmapImage bmp = new BitmapImage();
bmp.SetSource(fileThumbnail); Image img = new Image();
img.Source = bmp;

关于 GetThumbnailAsync 的详细用法,我的好朋友林德熙有更详细的说明,参见:win10 uwp 获得缩略图

优化 UWP 中图片的内存占用的更多相关文章

  1. [转帖]Linux中buff/cache内存占用过高解决办法

    Linux中buff/cache内存占用过高解决办法 https://www.cnblogs.com/rocky-AGE-24/p/7629500.html /proc/sys/vm/drop_cac ...

  2. 项目中Map端内存占用的分析

      最近在项目中开展重构活动,对Map端内存尽量要省一些,当前的系统中Map端内存最高占用大概3G左右(设置成2G时会导致Java Heap OOM).虽然个人觉得占用不算多,但是显然这样的结果想要试 ...

  3. 使用ExpandableListView以及如何优化view的显示减少内存占用

    上篇博客讲到如何获取手机中所有歌曲的信息.本文就把上篇获取到的歌曲按照歌手名字分类.用一个ExpandableListView显示出来. MainActivity .java   public cla ...

  4. Linux中buff/cache内存占用过高解决办法

    在Linux系统中,我们经常用free命令来查看系统内存的使用状态.在一个centos7的系统上,free命令的显示内容大概是这样一个状态: 这个命令几乎是每一个使用过Linux的人必会的命令,但越是 ...

  5. C#中XmlSerializer的内存占用问题

    被XmlSerializer掉坑里了,爬了一晚上才出来. 本来实现一个功能,从数据库中查出一堆数据(比较多,几十万,不过,是分批查出来的),查出来的数据包含了一个XML字符串,代码中对其进行序列化,一 ...

  6. Linux 中 Buffer/Cache内存占用过高解决方法

    在Linux系统中,我们经常用free命令来查看系统内存的使用状态.在一个RHEL6的系统上,free命令的显示内容大概是这样一个状态: 这里的默认显示单位是kb,我的服务器是128G内存,所以数字显 ...

  7. SqlServer性能优化,查看CPU、内存占用大的会话及SQL语句

    1,查看CPU占用量最高的会话及SQL语句   select spid,cmd,cpu,physical_io,memusage, (select top 1 [text] from ::fn_get ...

  8. 关于Android应用中图片占用内存浅谈

    从事过移动端应用开发的童鞋应该都清楚,内存是非常宝贵的资源.如果能很好的利用有限的内存,对应用性能的提升会有很大的帮助.在实际应用开发中图片内存占整个应用非常大的比重,我们只有了解图片是如何加载到内存 ...

  9. Android性能优化之利用LeakCanary检测内存泄漏及解决办法

    前言: 最近公司C轮融资成功了,移动团队准备扩大一下,需要招聘Android开发工程师,陆陆续续面试了几位Android应聘者,面试过程中聊到性能优化中如何避免内存泄漏问题时,很少有人全面的回答上来. ...

随机推荐

  1. Dive into Spring framework -- 了解基本原理(二)--设计模式-part2

    Template模式 Template模式顾名思义是提供了一种模板,也就是针对某种业务提供了模范框架.这个在spring中是属于核心模式的,因为其ApplicationContext抽象类就是模板模式 ...

  2. cygwin下安装软件

    cygwin下安装软件cygwin工具安装新的软件和常见的命令windows8.1下安装Cygwin并通过apt-cyg安装软件包Cygwin利用apt-cyg安装gcc.g++.make和gdb 首 ...

  3. svn 教程

    1.将文件checkout到本地目录 svn checkout path(path是服务器上的目录)   例如:svn checkout svn://192.168.1.1/pro/domain    ...

  4. Nginx安装和使用

    Nginx简介 nginx不单可以作为强大的web服务器,也可以作为一个反向代理服务器,而且nginx还可以按照调度规则实现动态.静态页面的分离,可以按照轮询.ip哈希.URL哈希.权重等多种方式对后 ...

  5. [nodejs]国内npm安装nodejs modules失败的几个解决方案

    使用npm安装node模块时经常有卡住安装失败的情况,如图所示.原因在于npm服务器在美国,还有就是某强大的防火墙作用.这样的问题导致很多新手放弃使用node,几乎每天都有新手再问这个问题.现在分享一 ...

  6. Comprehensive Python Cheatsheet

    ToC = { '1. Collections': [List, Dict, Set, Range, Enumerate, Namedtuple, Iterator, Generator], '2. ...

  7. Ubuntu 无法获得锁

    使用ubuntu安装pip 时,出现以下错误: E: 无法获得锁 /var/cache/apt/archives/lock – open (11 资源临时不可用) E: 无法锁定下载目录 解决方法: ...

  8. Ubuntu 安装GNU Scientific library(GSL)

    注: 此系列为自己之前所搭建网站内容. 由于论文数据处理的需要,需要使用libeemd这个包,需要安装gsl科学库,windows下没有办法,只能转战ubuntu进行科学计算. GSL(GNU Sci ...

  9. Slasher Flick

    打不死的小强! 返回一个数组被截断n个元素后还剩余的元素,截断从索引0开始. 这是一些对你有帮助的资源: Array.slice() Array.splice() 按照提供的第一种方法,代码如下: f ...

  10. yum 数据库报错与重构

    [root@dhcp yum.repos.d]# cd /var/lib/rpm/ [root@dhcp rpm]# rm __db.* -rf[root@dhcp rpm]# rpm --rebui ...