Bitmap 是Android系统中一个非常重要的类,也是作为Android开发工程师必须掌握的一个技术点。其中最为重要的就是高效的加载Bitmap。也许在桌面端软件中这并不是一个值得考虑的问题,最起码不是优先级最高的问题,直接显示就可以了。但是放到移动设备上,由于移动设备内存等其条件的限制,以及Android对于单个应用的内存限制,通常16M,所以导致在加载Bitmap的时候很容易导致内存溢出,因此我们要学会如何正确高效的加载Bitmap。
这里所说的高效加载,就是要在保证软件显示效果的情况下,尽量减少图片所占的内存,通常的方法就是根据具体的需求,采用不同的压缩方式对原图进行压缩,然后在软件中显示压缩后的图片,自然而然的也就减少了内存消耗。那么如何计算图片所占的内存的大小呢?
计算公式如下 :
widthheight一个像素所占的字节数。其中width和height分别表示图片的宽高
其中一个像素所占的字节数和图像的色彩模式有关,不同的色彩模式所占的字节数是不同的,详情如下:
ALPHA_8
表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度
ARGB_4444
表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节
ARGB_8888
表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节
RGB_565
表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节
举例说明,一张10241024像素的图片,如果采用ARGB_8888格式存储的话,那么它占据的内存为10241024*4,也就是4M。
图片压缩的方式有多种,这里主要介绍采样率压缩,可以通过BitmapFactory.Options来压缩图片,主要是通过设置它的inSampleSize 参数,也就是采样率。当采样率为1时,采样后的图片大小和原始图片相同,当采样率为2时,采样后的图片大小的宽高为原始图片的1/2,根据公式可以知道采样后的图片所占的内存为原图的1/4。
由上文可知,通过采样率是可以有效的加载图片的,但是如何获取合适的采样率呢,其实根据我们需要的图片大小和原图的大小,可以很简单的求出合适的采样率:
/**
* 高效的加载图片(采样率压缩方法)
*
* @return
*/
public static Bitmap decodeSampledBitmapFromResurce(Resources res, int resID, int reqWidth, int reqHeight) {
//第一步:将BitmapFactory.Options 的inJustDecodeBounds 参数设置true并加载图片
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resID, options);
options.inSampleSize = calculateInSample(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resID, options);
}
/**
* 计算出最合适的采样率,即(inSampleSize)
*
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
private static int calculateInSample(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;
while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}