【Google官方教程】第一课:高效地加载大Bitmap(位图)
来源:互联网 发布:盆景种子淘宝哪家好 编辑:程序博客网 时间:2024/05/14 13:27
在Google最新的文档中,提供了一系列含金量相当高的教程。因为种种原因而鲜为人知,真是可惜!Ryan将会细心整理,将之翻译成中文,希望对开发者有所帮助。
本系列是Google关于展示大Bitmap(位图)的官方演示,可以有效的解决内存限制,更加有效的加载并显示图片,同时避免让人头疼的OOM(Out Of Memory)。
-------------------------------------------------------------------------------------
译文:
图像可以有各种各样的形状和大小。在很多情况下,它们往往会比典型的应用UI界面所需要的更大。例如,系统的Gallery程序展示使用Android设备的摄像头拍摄的照片的分辨率往往要远高于设备的屏幕密度。考虑到你所使用的内存有限,理想的情况是你只会想加载一个分辨率相对较低的图片到内存中来。低分辨率版本的图片与相应UI组件的尺寸应该是相匹配的。一张高分辨率的图片并不能带给你任何可见的好处,却要占据着宝贵的内存,以及间接导致由于动态缩放引起额外的性能开销。
这节课将向你演示如何解码大图片,通过加载较小的图片样本以避免超出应用的内存限制。
读取Bitmap(位图)的尺寸和类型
BitmapFactory提供了几种解码方式(decodeByteArray(), decodeFile(), decodeResource()等等),以便从多种资源中创建一个Bitmap(位图)对象。可以根据你的图片数据来源选择最合适的解码方式。这些方法视图为构造Bitmap对象分配内存,因此很容易导致OutOfMemory(OOM)异常。每一种解码方式都有额外的特征,你可以通过BitmapFactory.Options类指定解码方法。在解码图片的时候设置inJustDecodeBounds属性为true,可以避免内存分配,返回的bitmap对象为null却可以设置outWidth, outHeight和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;
将缩小版的图片加载到内存中
现在图片的尺寸已经知道了,这些信息可以用来决定是将一个完整尺寸的图片加载到内存中,还是应该用一个图片的子样本来取代它。这里有一些可供考虑的因素:
- 估计加载全尺寸的图片所要消耗的内存
- 在考虑应用中其他内存需求的情况下,你愿意给加载这个图片分配的内存空间。
- 准备加载该图像的目标ImageView或者UI组件的尺寸
- 当前设备的屏幕的尺寸和密度
例如,如果最终只是要在ImageView中显示一张128*96px大小的缩略图,直接加载1024*768px的图片是非常不值得的。
为了告诉解码器如何对图像进行采样,加载更小版本的图片,需要在BitmapFactory.Options对象中将inSampleSize设置为true。例如,一张分辨率为2048*1536px的图像使用inSampleSize值为4的设置来解码,产生的Bitmap大小约为512*384px。相较于完整图片占用12M的内存,这种方式只需0.75M内存(假设Bitmap配置为ARGB_8888)。这里有一个方法用来计算基于目标高宽的sample size的值:
01
public
static
int
calculateInSampleSize(
02
BitmapFactory.Options options,
int
reqWidth,
int
reqHeight) {
03
// Raw height and width of image
04
final
int
height = options.outHeight;
05
final
int
width = options.outWidth;
06
int
inSampleSize =
1
;
07
08
if
(height > reqHeight || width > reqWidth) {
09
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
}
提示:使用2的次幂来设置inSampleSize值可以使解码器执行地更加迅速、更加高效。但是,如果你想在内存或者硬盘上缓存一个调整过大小的图片,通常还是解码到合适的图片尺寸更加节省空间。
要使用这个方法,首先要使用inJustDecodeBounds为true来解码尺寸信息,将options传递过去使用新的inSampleSize值再次解码并且要将inJustDecodeBounds值设置为false。
01
public
static
Bitmap decodeSampledBitmapFromResource(Resources res,
int
resId,
02
int
reqWidth,
int
reqHeight) {
03
04
// First decode with inJustDecodeBounds=true to check dimensions
05
final
BitmapFactory.Options options =
new
BitmapFactory.Options();
06
options.inJustDecodeBounds =
true
;
07
BitmapFactory.decodeResource(res, resId, options);
08
09
// 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
}
1
mImageView.setImageBitmap(
2
decodeSampledBitmapFromResource(getResources(), R.id.myimage,
100
,
100
));
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 【Google官方教程】第一课:高效的加载大Bitmap(位图)
- 第一课:高效地加载大Bitmap(位图)
- 第一课:高效地加载大Bitmap(位图)
- 【Google官方教程】前言:高效地显示Bitmap(位图)
- 高效地加载大Bitmap(位图)
- 高效地加载大Bitmap(位图)
- 高效地加载大Bitmap
- 高效地显示Bitmap图片 1 - 有效率地加载大尺寸的位图
- 高效的加载大Bitmap(位图)
- 【Android Training - 09】高效地显示Bitmap图片 [ Lesson 1 - 有效率地加载大尺寸的位图]
- html5 CSS3 渐变按钮
- hw 9.11
- 图片双缓存加载
- 启用Confluence远程接口调用(Remote API)
- win8 安装office2013,安装最后又回滚,安装失败(替换过 store)
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 我的Android进阶之旅------>Android如何去除GridView的按下或点击选中后的背景效果
- C++对象序列化方案对比
- java 调用 dll
- 处理器结构及其工作原理
- java反射
- Property Animation(属性动画)
- 对Python中文分词模块结巴分词算法过程的理解和分析
- MFC —— 线程控制主窗口的控件