转载:http://m.oschina.net/blog/75186

在Android平台上内存溢出是一件很头疼的事情,但解决办法还是有的,今天来翻译一篇谷歌官方提供的解决方案,原文可以参见:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html。

更有效地加载大的图片

图片有不同的形状可大小,在很多情况下他们总是大于一个典型应用UI的要求。例如,系统提供的Gallery程序显示了手机相机拍摄的图片,这些图片的分辨率总是大于设备屏幕的分辨率。

考虑到跟有限的设备内存打交道,理想情况下,你只需要加载在内存中的较低分辨率版本。分辨率较低的UI组键需要与显示它的大小相匹配。具有更高的分辨率的图像并不会带来显而易见的好处,但是仍然占用了宝贵的内存和因为缩放带来了额外的性能开销。

这节课将要通过载入一个较小的二次取样的小图片带你来编码一个大的图片而不需要超过每个程序最大的内存。

读取图片的尺寸和类型

BitmapFactory类提供了一些列创建不同图片种类的编码方式,例如:decodeByteArray(),decodeFile(),decodeResource()等等。基于你的图片数据来源选择一个最合适的编码方式。这些编码方法试图为创建Bitmap分配内存,因此可以很容易地导致OutOfMemory异常。每个类型的解码方法有额外的签名,让您指定通过BitmapFactory.Options类的解码选项。通过设置BitmapFactory.Options的inJustDecodeBounds属性设置为true,可以解码避免内存分配,返回的Bitmap为空,但返回outWidth,outHeight和outMimeType。这种技术使您可以读取的图像数据的尺寸和类型在内存分配之前。

view source print ?
1 BitmapFactory.Options options =newBitmapFactory.Options();
2 options.inJustDecodeBounds =true;
3 BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
4 intimageHeight = options.outHeight;
5 intimageWidth = options.outWidth;
6 String imageType = options.outMimeType;

为了避免java.lang.OutOfMemory异常,检查解码前的位图的尺寸,除非您绝对信任的来源,以提供可预见的大小的图像数据,适合有限的内存空间。

加载到内存中的一个缩减版本

现在的图像尺寸是已知的,它们可以被用来决定是否应加载到内存或二次采样的版本,而不是应装入完整的图像。这里有一些要考虑的因素:

  • 估计载入一张完整图像的内存使用
  • 你愿意投入到这个图片加载应用程序的任何其他内存要求的内存量。
  • 图像要加载到的目标的ImageView或UI组件的尺寸。
  • 当前设备的屏幕大小和密度

例如,没有必要把一个1024×768像素的图像加载到内存中,如果它最终会被显示在一个ImageView 128×96像素的缩略图。告诉图像解码器,加载到内存中的一个较小的版本,设置BitmapFactory.Options对象中的inSampleSize。例如,与2048×1536分辨率的图像,设置其inSampleSize为4(即Width为1/4,Height为1/4,整个图像大小为1/16)将产生一个约512×384的位图。载入到内存使用完整的图像(假设ARGB_8888位图配置)0.75MB,而超过12MB。这里有一个方法来计算的样本大小目标的宽度和高度上的值:

view source print ?
01 publicstaticintcalculateInSampleSize(
02 BitmapFactory.Options options,intreqWidth,intreqHeight) {
03 // 图像原始高度和宽度
04 finalintheight = options.outHeight;
05 finalintwidth = options.outWidth;
06 intinSampleSize =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 returninSampleSize;
16 }

注意:inSampleSize 设置为2的平方则编码速度更快更高效。不过,如果你打算在内存或磁盘上的缓存调整过大小的版本,它通常还是值得解码到最合适的图像尺寸,以节省空间。

设置为true inJustDecodeBounds使用这种方法,首先解码,通过选项,然后解码再次使用新inSampleSize值并inJustDecodeBounds设置为false:

view source print ?
01 publicstaticBitmap decodeSampledBitmapFromResource(Resources res,intresId,
02 intreqWidth,intreqHeight) {
03
04 // 首先设置 inJustDecodeBounds=true 来检查尺寸
05 finalBitmapFactory.Options options =newBitmapFactory.Options();
06 options.inJustDecodeBounds =true;
07 BitmapFactory.decodeResource(res, resId, options);
08
09 // 计算压缩比例
10 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
11
12 // 设置inJustDecodeBounds为false
13 options.inJustDecodeBounds =false;
14 returnBitmapFactory.decodeResource(res, resId, options);
15 }

这种方法使很容易地装入一个ImageView显示一个100×100像素的缩略图任意大尺寸位图,在下面的示例代码所示:

view source print ?
1 mImageView.setImageBitmap(
2
3 decodeSampledBitmapFromResource(getResources(), R.id.myimage,100,100));

更多相关文章

  1. FFmpeg编译MediaCodec
  2. 【Android】使用Gallery组件实现循环显示图像
  3. android内从泄漏
  4. Bitmap.Options和LruCache——Android高效加载大图、多图解决方
  5. Android获取视频文件某一帧并设置图片
  6. 【Android性能优化】Android图片加载方案--Bitmap的内存管理和优
  7. Android(安卓)FFmpeg系列——7 实现快进/快退功能
  8. Android中MAT、GIMP查看内存占用
  9. android图像绘制(一)多种方法做图像镜像

随机推荐

  1. 2020-08-31 2020常用面试题
  2. Android实现搜索历史功能
  3. 解决eclipse中查看android工程代码出现an
  4. 【Android】上传代码至JCenter
  5. Kotlin学习笔记---持续更新中
  6. Android回顾/Intent的使用
  7. Android之Bundle类
  8. 使用Tensorflow部署手机端app之将TensorF
  9. 关于android生成debug和release版
  10. Android的页面管理控件ViewFlipper