Bitmap处理 之二高效处理大图片
2015-09-07 09:44
260 查看
图片有各种各样的尺寸大小,许多情况下都会比需要的要大。比如系统图册显示的手机拍照的照片比你的设备的屏幕密度要高。
由于使用内存有限,最好是在内存中加载一个低分辨率版本。这个分辨率版本应该匹配显示它的UI组件的大小。一个高分辨率的位图没有啥好处,但仍然占用宝贵的内存控件而且带来额外的性能开销。
这篇文章将说如何加载一个更小的图片样本在内存中。
为了避免 java.lang.OutOfMemory 异常,在解析前先核对Bitmap的尺寸,除非你有绝对的把握你的图片不会造成内存溢出。
估算加载完整图片使用的内存大小。
加载了完整图片,给应用其他的内存需求大小
目标Imageview尺寸或者加载图片的UI组建大小
当前设备屏幕尺寸或者大小
告诉解码器对Image进行采样,加载一个较小版本图片到内存中,设置BitmapFactory.Options 对象inSampleSize为true。比如一个2048*1536密度的图片,inSampleSize为4生成的样品图就是512*384。加载这个样品需要内存0.75MB,而不是原来的12MB。下面提供了方法计算样本大小。
用下面地方法,第一步设置inJustDecodeBounds = true,然后通过新的inSampleSize解码,最后设置inJustDecodeBounds = false。
这个方法就可以把任意尺寸图显示成100*100的缩略图
由于使用内存有限,最好是在内存中加载一个低分辨率版本。这个分辨率版本应该匹配显示它的UI组件的大小。一个高分辨率的位图没有啥好处,但仍然占用宝贵的内存控件而且带来额外的性能开销。
这篇文章将说如何加载一个更小的图片样本在内存中。
读取Bitmap尺寸和类型
BitmapFactory类提供了几个解析方法,能从几种资源创建Bitmap。基于你Image资源选出最恰当的方法。这些方法会为创建Bitmap分配内存,因此可能会造成OutOfMemory异常。每种解码方法都可以让你通过BitmapFactory.Options设置标签。设置inJustDecodeBounds 为true,解码的时候会避免内存的分配,返回的bitmap对象为空,但是却可以得到 outWidth, outHeight 和outMimeType。这个技术可以是你在生成Bitmap之前获得到图片的尺寸和类型。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 异常,在解析前先核对Bitmap的尺寸,除非你有绝对的把握你的图片不会造成内存溢出。
加载一个按比例缩小版本到内存中
现在知道了图片的尺寸,就能知道到底是原图加载到内存中还是加载一个样品。下面几点可以考虑:估算加载完整图片使用的内存大小。
加载了完整图片,给应用其他的内存需求大小
目标Imageview尺寸或者加载图片的UI组建大小
当前设备屏幕尺寸或者大小
告诉解码器对Image进行采样,加载一个较小版本图片到内存中,设置BitmapFactory.Options 对象inSampleSize为true。比如一个2048*1536密度的图片,inSampleSize为4生成的样品图就是512*384。加载这个样品需要内存0.75MB,而不是原来的12MB。下面提供了方法计算样本大小。
public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // 原始图片大小 final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; //计算最大的压缩比例值都是2的幂次方,而且宽和高大于被要求 //的宽和高。 while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; }
用下面地方法,第一步设置inJustDecodeBounds = true,然后通过新的inSampleSize解码,最后设置inJustDecodeBounds = false。
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // 第一步inJustDecodeBounds=true 检查尺寸大小 final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // 计算样本尺寸 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // 进行采样 options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); }
这个方法就可以把任意尺寸图显示成100*100的缩略图
mImageView.setImageBitmap( decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
相关文章推荐
- 类别 category 以及类扩展
- app引导页(背景图片切换加各个页面动画效果)
- android动画:头像在两个界面的移动效果
- iOS学习笔记22- 解决RegexKitLite编译报错
- HDU 5428
- 归并排序的递归与非递归实现java
- Library cache lock/pin详解
- 读取文件夹下所有文件
- Android闹钟 AlarmManager的使用
- 苹果个人开发者账号如何升级成公司账号
- C++ 字符串指针与字符串数组
- 欢迎使用CSDN-markdown编辑器
- navicat 快捷键
- workflow 安装问题&没有流程树
- logback 配置详解(一)
- MFC六大核心机制之一MFC程序的初始化
- 宏定义的黑魔法 - 宏菜鸟起飞手册
- java IO流分析,java文件读写
- [Linux] - Virtualbox-CentOS动态增加分区空间方法
- 61单片机项目 - 定时器Timer A/B