高效地显示Bitmap图片 1 - 有效率地加载大尺寸的位图

简介:

http://blog.csdn.net/kesenhoo/article/details/7489243

Loading Large Bitmaps Efficiently [有效地加载大尺寸位图]

  • 图片有不同的形状与大小。在大多数情况下它们的实际大小都比需要呈现出来的要大很多。例如,系统的Gallery程序会显示那些你使用设备camera拍摄的图片,但是那些图片的分辨率通常都比你的设备屏幕分辨率要高很多。
  • 考虑到程序是在有限的内存下工作,理想情况是你只需要在内存中加载一个低分辨率的版本即可。这个低分辨率的版本应该是与你的UI大小所匹配的,这样才便于显示。一个高分辨率的图片不会提供任何可见的好处,却会占用宝贵的(precious)的内存资源,并且会在快速滑动图片时导致(incurs)附加的效率问。
  • 这一课会介绍如何通过加载一个低版本的图片到内存中去decoding大的bitmaps,从而避免超出程序的内存限制

Read Bitmap Dimensions and Type [读取位图的尺寸与类型]

  • BitmapFactory 类提供了一些decode的方法 (decodeByteArray()decodeFile()decodeResource(), etc.) 用来从不同的资源中创建一个Bitmap. 根据你的图片数据源来选择合适的decode方法. 那些方法在构造位图的时候会尝试分配内存,因此会容易导致OutOfMemory的异常。每一种decode方法都提供了通过BitmapFactory.Options 来设置一些附加的标记来指定decode的选项。设置 inJustDecodeBounds 属性为true可以在decoding的时候避免内存的分配,它会返回一个null的bitmap,但是 outWidthoutHeight 与 outMimeType 还是可以获取。这个技术可以允许你在构造bitmap之前优先读图片的尺寸与类型。
  1. BitmapFactory.Options options = new BitmapFactory.Options();  
  2. options.inJustDecodeBounds = true;  
  3. BitmapFactory.decodeResource(getResources(), R.id.myimage, options);  
  4. int imageHeight = options.outHeight;  
  5. int imageWidth = options.outWidth;  
  6. String imageType = options.outMimeType;  
  • 为了避免java.lang.OutOfMemory 的异常,我们在真正decode图片之前检查它的尺寸,除非你确定这个数据源提供了准确无误的图片且不会导致占用过多的内存。

Load a Scaled Down Version into Memory [加载一个按比例缩小的版本到内存中]

  • 通过上面的步骤我们已经知道了图片的尺寸,那些数据可以用来决定是应该加载整个图片到内存中还是加一个缩小的版本。下面有一些因素需要考虑:
    • 评估加载完整图片所需要耗费的内存。
    • 程序在加载这张图片时会涉及到其他内存需求。
    • 呈现这张图片的组件的尺寸大小。
    • 屏幕大小与当前设备的屏幕密度。
  • 例如,如果把一个原图是1024*768 pixel的图片显示到ImageView为128*96 pixel的缩略图就没有必要把整张图片都加载到内存中。
  • 为了告诉decoder去加载一个低版本的图片到内存,需要在你的BitmapFactory.Options 中设置 inSampleSize 为 true 。For example, 一个分辨率为2048x1536 的图片,如果设置 inSampleSize 为4,那么会产出一个大概为512x384的bitmap。加载这张小的图片仅仅使用大概0.75MB,如果是加载全图那么大概要花费12MB(前提都是bitmap的配置是 ARGB_8888). 下面有一段根据目标图片大小来计算Sample图片大小的Sample Code:
  1. public static int calculateInSampleSize(  
  2.             BitmapFactory.Options options, int reqWidth, int reqHeight) {  
  3.     // Raw height and width of image  
  4.     final int height = options.outHeight;  
  5.     final int width = options.outWidth;  
  6.     int inSampleSize = 1;  
  7.   
  8.     if (height > reqHeight || width > reqWidth) {  
  9.         if (width > height) {  
  10.             inSampleSize = Math.round((float)height / (float)reqHeight);  
  11.         } else {  
  12.             inSampleSize = Math.round((float)width / (float)reqWidth);  
  13.         }  
  14.     }  
  15.     return inSampleSize;  
  16. }  
  • Note: 设置 inSampleSize 为2对于decoder会更加的有效率,然而,如果你打算把调整过大小的图片Cache到磁盘上,设置为2也能够很有效的节省缓存的空间.
  • 为了使用这个方法,首先需要设置 inJustDecodeBounds 为 true, 把options的值传递过来,然后使用 inSampleSize 的值并设置 inJustDecodeBounds 为 false 来重新Decode一遍。
  1. public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,  
  2.         int reqWidth, int reqHeight) {  
  3.   
  4.     // First decode with inJustDecodeBounds=true to check dimensions  
  5.     final BitmapFactory.Options options = new BitmapFactory.Options();  
  6.     options.inJustDecodeBounds = true;  
  7.     BitmapFactory.decodeResource(res, resId, options);  
  8.   
  9.     // Calculate inSampleSize  
  10.     options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);  
  11.   
  12.     // Decode bitmap with inSampleSize set  
  13.     options.inJustDecodeBounds = false;  
  14.     return BitmapFactory.decodeResource(res, resId, options);  
  15. }  
  • 使用上面这个方法可以简单的加载一个任意大小的图片并显示为100*100 pixel的缩略图形式。像下面演示的一样:
  1. mImageView.setImageBitmap(  
  2.     decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100100));  
  • 你可以通过替换合适的BitmapFactory.decode* 方法来写一个类似的方法从其他的数据源进行decode bitmap。


相关文章
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的软件工程项目管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的软件工程项目管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
211 1
|
JavaScript 前端开发 Java
SpringBoot+Vue打造资产出入库管理系统(二)
SpringBoot+Vue打造资产出入库管理系统
690 2
|
机器学习/深度学习 自然语言处理 算法
Jieba分词的准确率提升:使用paddle模式进行分词(使用百度飞桨深度学习模型进行分词)
jieba中的paddle模式是指使用飞桨(PaddlePaddle)深度学习框架加速分词的一种模式。相对于传统的分词算法,paddle模式采用了深度学习模型,可以获得更高的分词准确度和更快的分词速度。
|
7月前
|
供应链 项目管理 容器
深入探索 BPMN、CMMN 和 DMN:从定义到应用的全方位解析
在当今快速变化的商业环境中,对象管理组织(OMG)推出了三种强大的建模标准:BPMN(业务流程模型和符号)、CMMN(案例管理模型和符号)和DMN(决策模型和符号)。它们分别适用于结构化流程管理、动态案例处理和规则驱动的决策制定,并能相互协作,覆盖更广泛的业务场景。BPMN通过直观符号绘制固定流程;CMMN灵活管理不确定的案例;DMN以表格形式定义清晰的决策规则。三者结合可优化企业效率与灵活性。 [阅读更多](https://example.com/blog)
深入探索 BPMN、CMMN 和 DMN:从定义到应用的全方位解析
|
12月前
|
前端开发 JavaScript
💥【exceljs】纯前端如何实现Excel导出下载和上传解析?
本文介绍了用于处理Excel文件的库——ExcelJS,相较于SheetJS,ExcelJS支持更高级的样式自定义且易于使用。表格对比显示,ExcelJS在样式设置、内存效率及流式操作方面更具优势。主要适用于Node.js环境,也支持浏览器端使用。文中详细展示了如何利用ExcelJS实现前端的Excel导出下载和上传解析功能,并提供了示例代码。此外,还提供了在线调试的仓库链接和运行命令,方便读者实践。
1203 5
|
JavaScript Java 测试技术
基于SpringBoot+Vue的高考志愿填报辅助系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue的高考志愿填报辅助系统的详细设计和实现(源码+lw+部署文档+讲解等)
262 1
若依如何创建二级页面菜单,点击目录后,右侧空白的悬浮空白的内容,点击系统管理的菜单管理,上级菜单点击主类木有个小三角,选择我们之前创建的主类目
若依如何创建二级页面菜单,点击目录后,右侧空白的悬浮空白的内容,点击系统管理的菜单管理,上级菜单点击主类木有个小三角,选择我们之前创建的主类目
|
负载均衡 关系型数据库 网络安全
Pgpool-II实现高可用+读写分离+负载均衡(二)---- 配置篇
Pgpool-II是一款工作在PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件。提供了连接池、复制、负载均衡、限制过多连接、看门狗、查询缓存等功能。本篇介绍详细配置。
|
前端开发 JavaScript NoSQL
SpringBoot+Vue打造资产出入库管理系统(一)
SpringBoot+Vue打造资产出入库管理系统
388 1