Android开发之Bitmap二次采样
Bitmap二次采样,听着好像是一个高大上的事,其实也就那么回事,今天我们就来看看Bitmap的二次采样问题。
1.为什么要二次采样
OK,那么首先我要 解决的一个问题就是为什么我们要二次采样?
不知道大家在开发App的过程中有没有遇到过类似于图片墙这样的功能?在做图片墙的时候你有没有遇到过OOM异常呢?遇到了又是怎么解决的?再比如我现在有一张100M大的图片,我想把这张图片用一个ImageView显示出来,那么你的ImageView能够显示出来这张图片吗?上面我们说的这两种情况其实都涉及到图片加载时内存溢出的问题,内存溢出可能发生在加载一张大图的时候,也有可能发生在加载多张普通小图的时候,如果我们不对图片做二次采样,那么OOM就是一把悬在头上的剑,随时可能会掉下。所以一定要对图片进行二次采样。事实上,我在手机上显示一张分辨率特别大的图片和显示一张分辨率小的图片(不要小的太离谱即可),对用户的视觉体验来说,并不会有多大变化,但是对我们手机的内存来说,影响却是非常巨大的。总而言之,二次采样就是为了避免图片加载时的OOM异常。
2.二次采样分别是哪两次?每次采样的目的是什么
既然是二次采样,那当然要分为两步了,下面我们来说说每次采样的主要工作:
1.第一次采样
第一次采样我主要是想要获得图片的压缩比例,假如说我有一张图片是200*200,那么我想把这张图片的缩略图显示在一个50*50的ImageView上,那我的压缩比例应该为4,那么这个4应该怎么样来获得呢?这就是我们第一步的操作了,我先加载图片的边界到内存中,这个加载操作并不会耗费多少内存,加载到内存之后,我就可以获得这张图片的宽高参数,然后根据图片的宽高,再结合控件的宽高计算出缩放比例。
2.第二次采样
在第一次采样的基础上,我来进行二次采样。二次采样的时候,我把第一次采样后算出来的结果作为一个参数传递给第BitmapFactory,这样在加载图片的时候系统就不会将整张图片加载进来了,而是只会加载该图片的一张缩略图进来,这样不仅提高了加载速率,而且也极大的节省了内存,而且对于用户来说,他也不会有视觉上的差异。
3.代码实现
说了这么多,我们来看看在Java代码中该怎么实现二次采样:
public class BitmapUtils {
/**
* @param filePath 要加载的图片路径
* @param destWidth 显示图片的控件宽度
* @param destHeight 显示图片的控件的高度
* @return
*/
public static Bitmap getBitmap(String filePath, int destWidth, int destHeight) {
//第一次采样
BitmapFactory.Options options = new BitmapFactory.Options();
//该属性设置为true只会加载图片的边框进来,并不会加载图片具体的像素点
options.inJustDecodeBounds = true;
//第一次加载图片,这时只会加载图片的边框进来,并不会加载图片中的像素点
BitmapFactory.decodeFile(filePath, options);
//获得原图的宽和高
int outWidth = options.outWidth;
int outHeight = options.outHeight;
//定义缩放比例
int sampleSize = 1;
while (outHeight / sampleSize > destHeight || outWidth / sampleSize > destWidth) {
//如果宽高的任意一方的缩放比例没有达到要求,都继续增大缩放比例
//sampleSize应该为2的n次幂,如果给sampleSize设置的数字不是2的n次幂,那么系统会就近取值
sampleSize *= 2;
}
/********************************************************************************************/
//至此,第一次采样已经结束,我们已经成功的计算出了sampleSize的大小
/********************************************************************************************/
//二次采样开始
//二次采样时我需要将图片加载出来显示,不能只加载图片的框架,因此inJustDecodeBounds属性要设置为false
options.inJustDecodeBounds = false;
//设置缩放比例
options.inSampleSize = sampleSize;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
//加载图片并返回
return BitmapFactory.decodeFile(filePath, options);
}
}
注释已经很详细了,大家自己看。
以上。
Android开发之Bitmap二次采样的更多相关文章
- android开发之bitmap使用
bitmap是android中重要的图像处理工具类,通过bitmap可以对图像进行剪切.旋转.缩放等操作,同时还可以指定格式和压缩质量保存图像文件. 一.拿到一个Bitmap对象 查看源码我们知道,B ...
- Android开发之Bitmap.Config.RGB_565
在学习xutils框架的时候,看到sample代码中有一行这样的代码: bitmapUtils.configDefaultBitmapConfig(Bitmap.Config.RGB_565); Bi ...
- 【转】Android开发之Bitmap的内存优化详解
本文来源:转载自: http://mobile.51cto.com/abased-410796.htm 在Android应用里,最耗费内存的就是图片资源.而且在Android系统中,读取位图Bitma ...
- android开发之Bitmap 、byte[] 、 Drawable之间的相互转换
一.相关概念 1.Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable),也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable) ...
- Android开发之Bitmap的高效加载
BitmapFactory类提供了四类方法:decodeFile, decodeResource, decodeStream和decodeByteArray 分别用于支持从文件系统,资源,输入流以及字 ...
- android开发之Animations的使用(二)
android开发之Animations的使用(二) 本博文主要讲述的是android开发中的animation动画效果的使用,和上一篇博文不同的是,此次四种动画效果,主要使用的是xml文件实现的,提 ...
- Android开发之Java集合类性能分析
对于Android开发者来说深入了解Java的集合类很有必要主要是从Collection和Map接口衍生出来的,目前主要提供了List.Set和 Map这三大类的集合,今天Android吧(ard8. ...
- Android开发之InstanceState详解
Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...
- 【Android UI】Android开发之View的几种布局方式及实践
引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理 ...
随机推荐
- CP_THREAD_ACP与CP_ACP
在使用MultiByteToWideChar的时候,大部分都知道上述两个参数,MSDN上的解释也是简单到极致.通常我们会选择使用CP_ACP,但是总有人会在没有真正明白它们之间的区别前使用CP_THR ...
- linux设备驱动那点事儿之平台设备理论篇
一:Platform总线 1.1概述 一个现实的linux设备驱动通常需要挂接在一种总线上,对于本身依附于PCI,USB,IIC,SPI等的设备而言,这自然不是问题,但是在嵌入式系统里面,SOC系统中 ...
- Redis 如何导出数据
Redis是一款支持多种数据类型的Key-Value数据库. 这里介绍下如何从Redis中导出数据. 数据是如何存储的?. Redis中是把数据保存到内存中的,但是它也会定期的把数据写会到硬盘中. R ...
- Linux下归档与压缩工具笔记
tar具体使用笔记 归档工具 tar 语法 功能 选项 常见搭配 压缩工具 bzip2 工具 使用方法 gzip 工具 zip 工具 归档工具 tar tar是一个开源的Linux/Unix中最广泛使 ...
- 【转】Java 内存模型及GC原理
一个优秀Java程序员,必须了解Java内存模型.GC工作原理,以及如何优化GC的性能.与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只有全面提升内存的管理效率,才能 ...
- Error:Could not open initscript class cache for initialization script 'C:\Users\Avishek\AppData\Local\Temp\asLocalRepo14.gradle' (C:\Users\Avishek.gradle\caches\2.2.1\scripts\asLocalRepo14_dkwbdtenxxg
Error:Could not open initscript class cache for initialization script 见鬼 Android Studio打开项目时遇到这个问题 昨 ...
- SSL双向认证(高清版)
介绍了SSL双向认证的一些基本问题,以及使用Nginx+PHP基于它搭建https的Webservice. 之前的方式只是实现1:1的模式,昨天同事继续实现了n:1的模式,这里我再整理记录下. 由于n ...
- Html笔记(八)其他标签
<pre></pre> :此标签内封装的文本数据格式将保持原样,包括空格和缩进等格式.常用于页面中显示带有缩进层次的代码. <p></p> :段落标签, ...
- 如何使用 RDP 或 SSH 连接到 Azure 虚拟机
使用 RDP 或 SSH 连接到 Azure 虚拟机 本文简要概述了如何使用远程桌面控制协议 (RDP) 或安全外壳(Secure Shell,SSH)客户端登录 Azure 虚拟机.它还包括要求和故 ...
- 搭建集群必备:windows如何使用Xshell远程连接(SSH)Linux
出处about云(http://www.aboutyun.com/blog-61-22.html)欢迎访问我的博客 首先介绍一下环境: (主机)操作系统:win7 虚拟机:vmware worksta ...