一、Bitmap简介
BitMap从字面的意思,很多人认为是位图,其实准确的来说,翻译成基于位的映射。用一个bit位来标记某个元素对应的Value, 而Key即是该元素。由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省。
这里只说一下在Android中的使用,Bitmap在Android中指的是一张图片,可以是jpg格式的,也可以是png格式等其他常见的图片格式 。
二、Android Bitmap主要创建方法
这里只说Bitmap高效加载的主要方法,其中创建Bitmap有四大种类方法分别是:
1、public static Bitmap decodeResource (Resources res, int id, BitmapFactory.Options opts)
参数
res 包含图像数据的资源对象
id 图像数据的资源的id
opts 可以为空,控制采样率和实付图像完全被解码的选项,或者仅仅返回大小
返回值
2、public static Bitmap decodeFile (String pathName, BitmapFactory.Options opts)
参数
pathName 解码文件的全路径名
opts 可以为空,控制采样率和实付图像完全被解码的选项,或者仅仅返回大小
Returns
返回解码后的位图,或者如果图像数据不能被解码返回为空,或者 如果选项不是空,如果选项要求仅仅返回大小(opts.outWidth and opts.outHeight)。
从文件中解码生成一个位图。如果支付的文件名为空,或者不能解码出一个位图,方法将返回空。
3、public static Bitmap decodeStream (InputStream is, Rect outPadding, BitmapFactory.Options opts)
参数
is 持有原始数据用于解码位图的输入流
outPadding 如果不为空,返回矩形的内边距如果位图存在,否则设置内边距为(-1,-1,-1,-1).如果没有位图返回空,内边距不改变
opts 可以为空,控制采样率和实付图像完全被解码的选项,或者仅仅返回大小
Returns
返回解码后的位图,或者如果图像数据不能被解码返回为空,或者 如果选项不是空,如果选项要求仅仅返回大小(opts.outWidth and opts.outHeight)。
从输入流中解码一个位图。如果输入了为空,或者不能解码位图,方法返回空。流的位置觉得解码数据从哪儿读取。
4、public static Bitmap decodeByteArray (byte[] data, int offset, int length, BitmapFactory.Options opts)
参数
data 压缩图像数据的字节数组
offset 图像数据偏移量,用于解码器开始从哪儿解析.
length 字节数,以偏移量开始,去解析
opts 可以为空,控制采样率和实付图像完全被解码的选项,或者仅仅返回大小
返回值
返回解码后的位图,或者如果图像数据不能被解码返回为空,或者 如果选项不是空,如果选项要求仅仅返回大小(opts.outWidth and opts.outHeight)。
从指定的字节数组中解码一个不可变的位图。
分别用于支持从资源、文件、输入流和字节数组加载一个Bitmap对象,其中decodeResource和decodeFile又间接的调用了decodeStream,这四类方法最终是在Android底层实现的,有对应的几个native方法。
三、Bitmap如何实现高效加载图片
核心思想是采用BitmapFactory.Options来加载需要的图片尺寸,BitmapFactory.Options通过按一定的采样率(inSampleSize)来加载缩小后的图片,然后将缩小后的图片放入ImageView中显示。这样就会降低内存占用从而在一定的程序上避免OOM,提高图片加载效率。
当inSampleSize即采样率为主1时,采样后的图片大小为原始图片的原始大小;当inSampleSize大于1时 ,比如为2时 ,那么采样后图片的宽/高为原始图片大小的不同1/2,而像素数为原图的1/4,其占有的内存大小也为原始图片的1/4. 比如一个10241024的图片,采用ARGB8888格式存储,那么它占有内存为102410244 ,即4MB。如果 inSampleSize=2时,在采样之后它的占用内存只有512512*2,,即1MB 。inSampleSize采样率必须要大于 1 ,才会缩小效果。采样率是以 2的次方形式递减的,所以官方文档中推荐以2的指数来取值。特殊情况比如:当inSampleSize小于等于1时,就相当于1 无缩放效果。当inSampleSize=3时,系统会选择2 来代替的。
三、Bitmap通过采样率高效加载图片代码实现
public static Bitmap decodeSampledBitmapFromResource(Resources res,int resId,int reqWidth,int reqHeight){
//1、创建 BitmapFactory.Options对像并inJustDecodeBounds设为true
final BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
BitmapFactory.decodeResource(res,resId,options);
//设置 inSampleSize
options.inSampleSize=calculateInSampleSize(options,reqWidth,reqHeight);
//4、将inJustDecodeBounds设为false
options.inJustDecodeBounds=false;
return BitmapFactory.decodeResource(res,resId,options);
}
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
//2、根据Optuins获取原始图片宽高outWidth\outHeight
final int width =options.outWidth;
final int height=options.outHeight;
int inSampleSize=1;
//3、根据原始宽高计算出采样率 inSampleSize
if (height>reqHeight||width>reqWidth){
final int halfWidth=width/2;
final int halfHeight=height/2;
//计算最大的采样值,即2的幂,并同时保持
//高度和宽度大于要求的高度和宽度
while ((halfWidth/inSampleSize)>=reqWidth&&(halfHeight/inSampleSize)>=reqHeight){
inSampleSize*=2;
}
}
return inSampleSize;
}
通过采样率加载图片遵循上面的四步。
网友评论