(DOC)Displaying Bitmaps Efficiently


本人才疏学浅,翻译的不对的地方请指出,而且本人不是针对原文一字一句翻译的,适当作些调整,翻译大概意思,并添加一些小批注。
这些文章提供了一个可行的解决办法,适合初学者应用,它介绍了各种处理图片的方式,可以应用在程序中,未必是完美的。

Displaying Bitmaps Efficiently这是文档中的新的一部分:大概翻译下内容:
这章覆盖了一些常用的技术,是关于处理Bitmap对象的,可以帮助您的UI快速响应,避免内存溢出。如果您不小心,可能很快地消耗了内存,导致程序的崩溃。抛出异常:java.lang.OutofMemoryError: bitmap size exceeds VM budget.

关于为什么在Android应用在加载Bitmap时有限制,主要有以下几点:
移动设备只有有限的系统资源,Android设备只有16mb可用于一个程序。android compatibility definition document(CDD)[url]http://source.android.com/compatibility/downloads.html [/url],第三节Virtual Machine Compatility 给出了不同屏幕和分辨率的最小应用内存需求说明,应用程序需要在这样的内存限制中优化。
Bitmap会消耗很多的内存,尤其像照片,摄像头在GalaxyNexus拍一张照片有2592*1936像素,如果bitmap使用ARGB_8888配置(2.3默认的),加载这张照片到内存需要消耗约19mb内存,(2592*1936*4bytes)。就超过了应用的内存限制了。

android的ui经常需要加载几张bitmap位图,像ListView,GridView,ViewPager这样的组件在屏幕上通常会有多张的位图。

Loading Large Bitmaps Efficiently
图片有各种大小,开状,多数情况下对于特定的android程序ui来说它们是偏大的。如Gallery应用显示照片跟摄像头的比就小得多了。

在内存受限的情况下,你只需要加载一些低分辨率的图片,一张大分辨率的图片并没有提高视觉效果,还占用更多的内存,
这节告诉您如何解码大的图片,而不超过系统的限制。

Read Bitmap Dimensions and Type
BitmapFactory类提供了一些解码的方法decodeByteArray(),decodeFile(),decodeResource()等,来创建一个位图资源。需要选择正确的方法来解析图片资源。这些方法会构造一个位图,然后申请内存,容易造成oome,每一个方法都有一个额外的信息为您 分配解码选项BitmapFactory.Options类,设置inJustDecodeBounds属性为true时,解码避免了内存占用,它不会返回位图信息,而设置了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;

避免oome的出现可以先判断dimensions,再解码
Load a Scaled Down Version into Memory
加载一个缩放后的版本到内存中,位图的dimensions从上面得到后,可用于决定是否位图可以加载到内存,或加载一个缩放后的版本。
这里给出一些因素供参考:
估计内存的消耗。
计算应用的其它部分占用的内存与当前图片应该占用的内存。
贴图目标需要多大的dimensions,如ImageView,或其它ui。
屏幕的大小与解析度。

如,显示在128x96像素的ImageView中不值得加载一个1024*768像素的图片。
在BitmapFactory.Options 设置inSampleSize的值就可以改变了。
如2048*1536像素的图片解码时inSampleSize=4,就会得到一个512*384大小的位图了,使用0.75mb内存,而不是12mb。
下面提供一个方法来计算 :
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;
}
注意:使用2的倍数会对解码更高效的(我估计是二进制的原因),
使用这个方法,首先需要options.inJustDecodeBounds = true;先解码一次,然后再使用新的inSampleSize值,options.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);
}
这就提供了简易的加载图片的方法了:
mImageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

剩下两篇下面继续


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值