本文译自:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

图片有各种形状和尺寸。在很多情况下,它们通常要大于显示图片用的用户界面(UI)。例如,系统的Gallery应用程序会显示Android设备的照相机所拍摄的照片,通常照片的分辨率要高于设备的屏幕密度。

由于内存的限制,你可能只想在内存中加载较低分辨率的图片版本。低分辨率版本应该跟显示它的UI组件尺寸相匹配。高分辨率的图片不会有益于显示,但是依然会消耗高贵的内存,并且由于缩放还会导致性能下降。

本文讲解如何用较小的采样版本来解码大位图,而不让其超过每个应用程序内存的限制。

读取位图的尺寸和类型

BitmapFactory类提供了几个解码方法(如decodeByteArray()、decodeFile()、decodeResource()等)来创建来自各种资源的位图(Bitmap)。基于图片数据源来选择最恰当的解码方法。这些方法尝试着给被创建的位图分配内存,内存很容易产生OutOfMemory异常。每种类型的解码方法都有一个附加的标识,这个标识会通过BitmapFactory.Options类让你指定解码选项。

inJustDecodeBounds属性设置为true,解码时会避免过度的内存分配,除了设置outWidthoutHeightoutMimeType属性设置以外的位图对象都会返回null。这种技术会允许你在构造(和分配内存)位图之前读取图片数据打的尺寸和类型。

BitmapFactory.Optionsoptions=newBitmapFactory.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异常,就要在解码之前检查位图的尺寸,除非你确信提供给你的图片数据源能够适合可用的内存。

把缩小的图片加载到内存中

获取图片的尺寸之后,就可以用它来判断是否可以把图片完整的加载到内存中,或者是降低采样率来加载图片。以下是要考虑的一些因素:

1.估算把图片完整的加载到内存时所有使用的内存;

2.除了图片的内存需求之外,应用程序的其他内存需求;

3.显示图片的UI组件的尺寸;

4.当前设备的屏幕尺寸和密度。

例如,把一个1024x768像素的图片完全加载到内存中,并在一个128x96像素的ImageView组件中,这种内存消耗是不值得的。

设置BitmapFactory.Options对象的inSampleSize属性,就可以告诉解码器降低采样率,把较小的分辨率的图片加载到内存中。例如,inSampleSize属性设置为4,那么分辨率为2048x1536的图片就可以解码为512x384像素的位图。这时所消耗的内存是0.75MB而不是12MB(假设位图是ARGB_8888形态)。以下是基于目标的宽度和高度来计算采样尺寸值的方法:

publicstaticintcalculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width ofimage
final int height = options.outHeight;
final int width = options.outWidth;
intinSampleSize = 1;

if (height > reqHeight || width > reqWidth) {

// Calculateratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);

// Choosethe smallest ratio as inSampleSize value, this will guarantee
// a finalimage with both dimensions larger than or equal to the
// requestedheight and width.
inSampleSize = heightRatio < widthRatio ?heightRatio : widthRatio;
}

return inSampleSize;
}

注意:inSampleSize值使用2的倍数会使解码器更快、更高效。但是,如果你只是打算在内存或硬盘上缓存调整后版本,那么通常采用最恰当的图片尺寸来解码,以便节省存储空间,这依然是值得的。

要使用这种方法,首先要把inJustDecodeBounds设置为true进行一次解码,然后再使用新的inSampleSize的值来再次解码,并把inJustDecodeBounds设置为false:

publicstaticBitmapdecodeSampledBitmapFromResource(Resourcesres,intresId,
int reqWidth, int reqHeight) {

// First decode withinJustDecodeBounds=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 withinSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);

这种方法使得把任意大尺寸的图片加载到一个显示100x100像素的小ImageView中来显示变得很容易。例如:

mImageView.setImageBitmap(
decodeSampledBitmapFromResource
(getResources(), R.id.myimage, 100, 100));

你可以使用类似过程对来自其他类型资源的位图进行解码,只需用相应的BitmapFactory.decode*方法来代替就可以了。

更多相关文章

  1. 高效显示Bitmap+listview冲突解决+图片内存缓存+硬盘缓存
  2. android:GLSurfaceView绘制bitmap图片及glViewport调整的效果
  3. Android实现照片选择显示-从相册选择或拍照选择
  4. Android(安卓)客户端性能优化(魅族资深工程师毫无保留奉献)
  5. android中显示网络图片
  6. Android开发资料:Android启动优化解析
  7. Android常用控件以及用法
  8. [置顶] android 优化那些事之图片缓存设计/如何高效的展示图片(
  9. 怎样在android中添加背景图片?

随机推荐

  1. Android中的Linear Layout
  2. Android修改文件和文件夹权限
  3. [Android]屏幕自适应布局
  4. cocos2.2.3 HelloCpp TestCpp android 环
  5. Android中的内存溢出和内存泄漏问题
  6. 分享45个android实例源码
  7. Android官方技术文档翻译——Application
  8. 实现Android的图片画廊控件ScrollGallery
  9. Android 隔一段时间重复执行某代码
  10. Android CTS测试Fail项修改总结(四)