Loading Large Bitmaps Efficiently
有效地加载大位图文件-Loading Large Bitmaps Efficiently
图像有各种不同的形状和大小。在许多情况下,他们往往比一个典型应用程序的用户界面(UI)所需要的资源更大。例如,系统的Gallery程序展示使用Android设备的照相机所拍摄的照片通常要比你的设备的屏幕密度的分辨率更高。
既然你所使用的内存有限,理想状况下你只想在内存中加载一个低分辨率的版本。低分辨率的方案应该匹配显示它的UI组件的大小。一个更高分辨率的图片不提供任何可见的好处,但是由于额外的缩放会导致额外的性能开销,仍然占用缩放之前的内存,。
这节课将引导你在不超过内存限制的情况下通过解码大型位图,在内存中加载一个较小的位图子样本。
读取一个位图的尺寸和类型-Read Bitmap Dimensions and Type
为了从多种资源来创建一个位图,BitmapFactory类提供了几个解码的方法(decodeByteArray(),decodeFile(),decodeResource(),等等)。根据你的图像数据资源选择最合适的解码方法。这些方法试图请求分配内存来构造位图,因此很容易导致OutOfMemory异常。每种类型的解码方法都有额外的特征可以让你通过BitMapFactory.Options类指定解码选项。当解码时避免内存分配可以设置inJustDecodeBounds属性为true,位图对象返回null但是设置了outWidth,outHeight和outMimeType。这种技术允许你在创建位图(和分配内存)之前去读取图像的尺寸和类型。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
为了避免java.lang.OutOfMemory异常,在解码位图之前请检查它的尺寸,除非你十分确定资源提供给你的可预见的图像数据正好满足你的内存。
加载一个缩小版本到内存中(Load a Scaled Down Version into Memory)
现在的图像尺寸都是已知的,他们可以被用来决定是否应该加载完整的图片到内存或者是否用一个缩小的版本去代替加载。以下是一些值得考虑的因素:
估计加载完整图像所需要的内存;
你承诺加载这个图片所需空间带给你的程序的其他内存需求;
准备加载图像的目标ImageView或UI组件尺寸;
当前设备的屏幕尺寸和密度;
例如,如果1024*768像素的图像最终被缩略地显示在一个128*96像素的ImageView中,就不值得加载到内存中去。
告诉解码器去重新采样这个图像,加载一个更小的版本到内存中,在你的BitmapFactory.Option对象中设置inSampleSize为true。例如,将一个分辨率为2048*1536的图像用 inSampleSize值为4去编码将产生一个大小为大约512*384的位图。加载这个到内存中仅使用0.75MB,而不是完整的12MB大小的图像(假设使用ARGB_8888位图的配置)。这里有一个方法在目标的宽度和高度的基础上来计算一个SampleSize的值。
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)reqHeight);
} else {
inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}
NOTE:使用2的幂数设置inSampleSize的值可以使解码器更快,更有效。然而,如果你想在内存或硬盘中缓存一个图片调整后的版本,通常解码到合适的图像尺寸更适合来节省空间。
要使用这种方法,首先解码,将inJustDecodeBounds设置为true,将选项传递进去,然后再次解码,在使用新的inSampleSize值并将inJustDecodeBounds设置为false:
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
这种方法可以很容易地加载任意大小的位图到一个ImageView显示一个100x100像素的缩略图,如下面的示例代码所示:
mImageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
你可以按照类似的过程,用适当的BitmapFactory.decode*中的方法去解码一个从其他资源得到的位图
Loading Large Bitmaps Efficiently的更多相关文章
- Displaying Bitmaps Efficiently 显示图片相关
http://developer.android.com/training/displaying-bitmaps/index.html .手机内存资源有限 .Bitmap占用的内存大 .App有时需要 ...
- trying to draw too large(106,975,232 bytes) bitmap.
Loading Large Bitmaps Efficiently This lesson teaches you to Read Bitmap Dimensions and Type Load a ...
- [译]Android调整图像大小的一些方法
翻译自 某大神在Stack Overflow里的自问自答 (一般我们将Bitmap翻译为位图,但为了更好理解,在本文中我将它翻译成图像): 我们在开发的时候,经常需要从服务器中加载图像到客户端中,但有 ...
- [原] Android持续优化 - 提高流畅度
一.形象的感官一下流畅度概念 1. 这是官方给出的概念:Android流畅运行,需要运行60帧/秒, 则需要每帧的处理时间不超过16ms. 2. 每秒帧数,实际上就是指动画或视频每秒放映的画面数.因此 ...
- 学习笔记 - 深究Bitmap压缩避免OOM的核心inSampleSize的最佳取值
/** * 测试代码,通过在SDCard根目录放置几种不同大小的图片, 来自动测试压缩方式是否有效同时看是否会内存不够. * * @since * By:AsionTang * At:2014年3月2 ...
- android 高效显示Bitmap - 开发文档翻译
由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接 Displaying Bitmaps Efficiently 高效显示Bitmap Lea ...
- Android Training
Building Apps with Content Sharing Simple Data --> Intent && ActionProvider 介绍如何让应用程序共享简单 ...
- Android训练课程(Android Training) - 高效的显示图片
高效的显示图片(Displaying BitmapsEfficiently) 了解如何使用通用的技术来处理和读取位图对象,让您的用户界面(UI)组件是可响应的,并避免超过你的应用程序内存限制的方式.如 ...
- 【Android】自己定义圆形ImageView(圆形头像 可指定大小)
近期在仿手Q的UI,这里面常常要用到的就是圆形头像,看到 在android中画圆形图片的几种办法 这篇文章,了解了制作这样的头像的原理.只是里面提供的方法另一个不足的地方就是不能依据实际需求改变图片的 ...
随机推荐
- Spring Boot同时开启HTTP和HTTPS服务
由于Spring Boot中通过编码开启HTTPS服务比较复杂,所以官方推荐通过编码开启HTTP服务,而通过配置开启HTTPS服务. Spring Boot的application.yml中添加如下配 ...
- XML的语法
XML的语法 文档声明: 写法 <?xml version="1.0" ?> 文档声明必须出现在xml文件的第一行和第一列的位置 属性: version="1 ...
- qduoj su003 数组合并
描述 现在呢有两个整形数组,a[n]和b[m],而且已经知道这两个数组都是非降序数组.现在呢就有一个工作需要你来完成啦.对于a中的每个元素a[i]在b中寻找<=a[i] 的元素个数,个数记为x[ ...
- LeetCode Image Smoother
原题链接在这里:https://leetcode.com/problems/image-smoother/description/ 题目: Given a 2D integer matrix M re ...
- 洛谷 P2822 组合数问题
题目描述 组合数C_n^mCnm表示的是从n个物品中选出m个物品的方案数.举个例子,从(1,2,3) 三个物品中选择两个物品可以有(1,2),(1,3),(2,3)这三种选择方法.根据组合数的 ...
- 常用Request对象获取请求信息
Request.ServerVariables(“REMOTE_ADDR”) ‘获取访问IPRequest.ServerVariables(“LOCAL_ADDR”) ‘同上Request.Serve ...
- [转]使用Flexible实现手淘H5页面的终端适配
曾几何时为了兼容IE低版本浏览器而头痛,以为到Mobile时代可以跟这些麻烦说拜拜.可没想到到了移动时代,为了处理各终端的适配而乱了手脚.对于混迹各社区的偶,时常发现大家拿手机淘宝的H5页面做讨论—— ...
- MySQL自带的性能压力测试工具mysqlslap详解
使用语法如下:# mysqlslap [options] 常用参数 [options] 详细说明: --auto-generate-sql, -a 自动生成测试表和数据,表示用mysqlslap工具自 ...
- Maven Build错误。
错误: No goals have been specified for this build. You must specify a valid lifecycle phase or a goal ...
- VerilogHDL编译预处理
编译预处理语句 编译预处理是VerilogHDL编译系统的一个组成部分,指编译系统会对一些特殊命令进行预处理,然后将预处理结果和源程序一起在进行通常的编译处理.以”`” (反引号)开始的某些标识符是编 ...