Bitmap高效加载图片
2016-07-09 18:28
225 查看
一、什么是Bitmap
Bitmap在Android中指一张图,格式不定。BitmapFactory提供了四类方法:decodeFile.decodeResource
decodeStream和decodeByteArray,分别支持从文件,资源,输入流以及字节数组加载出一个bitmap对象,
其中decodeFile和decodeResource间接调用了decodeStream。
二、高效加载的核心原理
怎么高效地加载Bitmap,可以说之加载所需尺寸就行了,一般来说原始图片都比显示出来的图片要大,
越大的图片加载速度、效率就会越低,那么我们在加载之前对图片进行缩放处理,这样使得效率提高,而且
可以在一定程度上避免OOM我们通过BitmapFactory.Options来缩放图片,主要是其中的inSampleSize参数,
即采样率。当inSampleSize为1时,采样后的图片大小为原始大小;当inSampleSize为2时,那么采样后的宽
高均为原图的1/2,而像素数为原图的1/4,内存占用也为原图的1/4,在Goole官方文档中还指出
inSampleSize的取值应该总为2的指数,比如:1,2,4,8...如果不为2的指数那么系统会自动向下取整并选择
一个最接近2的指数来代替。
三、实际开发中的意外情况
另外考虑以下实际情况,假设我们用ImageView来显示图片,当ImageView的大小为100x100像素,而图片
原始大小为200x200,那么只需将采样率inSampleSize设置为2即可,但是如果图片大小为200x300呢?如果采
样率选择2,那么缩放后图片大小为100x150,也可以继续用ImageView,如果采样率为3,那么缩放后图片大小
就会小于ImageView,所期望的大小,那么图片会被自动拉伸而导致模糊
(ImageView底层代码原理,当加载的资源与本身大小不一样时,会自动调用requestLayout(),然后调用
父节点的requestLayout()重新布局,在此过程中会自动对资源进行缩放拉伸处理)
四、过程
获取采样率
1.将BitmapFactory.Options的inJustDecodeBounds参数设置为false,并加载图片(为了测量图片宽高)
2.从BitmapFactory.Options中取出图片的原始宽高信息(存放在options参数中)
3.根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize。
4.将BitmapFactory.Options的inJustDecodeBounds参数设置为false,并重新加载图片
注释:当inJustDecodeBounds为true时,只会解析图片的宽高信息,而不去加载图片
代码如下:
public class MainActivity extends AppCompatActivity { private ImageView im_1; private ImageView im_2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); im_1 = (ImageView) findViewById(R.id.im_1); im_2= (ImageView) findViewById(R.id.im_2); im_1.setBackgroundResource(R.drawable.tiantang); im_2.setImageBitmap(decodeSampledBitmapFromResources(getResources(),R.drawable.tiantang,100,100)); } private Bitmap decodeSampledBitmapFromResources(Resources res,int resId,int reqWidth,int reqHeight){ //1.找到BitmapFactory实例 BitmapFactory.Options options = new BitmapFactory.Options(); //2.设置inJustDecodeBounds参数为True options.inJustDecodeBounds = true; //3.得到BitmapFactory加载进来的图片 BitmapFactory.decodeResource(res, resId, options); //4.计算缩放比 options.inSampleSize =calculateInSampleSize(options,reqWidth,reqHeight); options.inJustDecodeBounds =false; return BitmapFactory.decodeResource(res,resId,options); } private int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){ int height = options.outHeight; int width = options.outWidth; int inSampleSize =1; //当图片宽高其中一个大于要求宽高 if(height>reqHeight||width >reqWidth){ int halfHeight = height/2; int halfWidth = width/2; //循环直到得到合适的采样率 while((halfHeight/inSampleSize)>=reqHeight && (halfWidth/inSampleSize)>=reqWidth){ inSampleSize *=2; } } return inSampleSize; } }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories