Bitmap 是Android系統(tǒng)中一個非常重要的類,也是作為Android開發(fā)工程師必須掌握的一個技術點蕊梧。其中最為重要的就是高效的加載Bitmap。也許在桌面端軟件中這并不是一個值得考慮的問題县恕,最起碼不是優(yōu)先級最高的問題峰搪,直接顯示就可以了。但是放到移動設備上个榕,由于移動設備內(nèi)存等其條件的限制篡石,以及Android對于單個應用的內(nèi)存限制,通常16M西采,所以導致在加載Bitmap的時候很容易導致內(nèi)存溢出凰萨,因此我們要學會如何正確高效的加載Bitmap。
這里所說的高效加載,就是要在保證軟件顯示效果的情況下胖眷,盡量減少圖片所占的內(nèi)存武通,通常的方法就是根據(jù)具體的需求,采用不同的壓縮方式對原圖進行壓縮珊搀,然后在軟件中顯示壓縮后的圖片冶忱,自然而然的也就減少了內(nèi)存消耗。那么如何計算圖片所占的內(nèi)存的大小呢境析?
計算公式如下 :
widthheight一個像素所占的字節(jié)數(shù)囚枪。其中width和height分別表示圖片的寬高
其中一個像素所占的字節(jié)數(shù)和圖像的色彩模式有關,不同的色彩模式所占的字節(jié)數(shù)是不同的簿晓,詳情如下:
ALPHA_8
表示8位Alpha位圖,即A=8,一個像素點占用1個字節(jié),它沒有顏色,只有透明度
ARGB_4444
表示16位ARGB位圖眶拉,即A=4,R=4,G=4,B=4,一個像素點占4+4+4+4=16位,2個字節(jié)
ARGB_8888
表示32位ARGB位圖憔儿,即A=8,R=8,G=8,B=8,一個像素點占8+8+8+8=32位忆植,4個字節(jié)
RGB_565
表示16位RGB位圖,即R=5,G=6,B=5,它沒有透明度,一個像素點占5+6+5=16位,2個字節(jié)
舉例說明谒臼,一張10241024像素的圖片朝刊,如果采用ARGB_8888格式存儲的話,那么它占據(jù)的內(nèi)存為10241024*4蜈缤,也就是4M拾氓。
圖片壓縮的方式有多種,這里主要介紹采樣率壓縮底哥,可以通過BitmapFactory.Options來壓縮圖片咙鞍,主要是通過設置它的inSampleSize 參數(shù),也就是采樣率趾徽。當采樣率為1時续滋,采樣后的圖片大小和原始圖片相同,當采樣率為2時孵奶,采樣后的圖片大小的寬高為原始圖片的1/2,根據(jù)公式可以知道采樣后的圖片所占的內(nèi)存為原圖的1/4疲酌。
由上文可知,通過采樣率是可以有效的加載圖片的了袁,但是如何獲取合適的采樣率呢朗恳,其實根據(jù)我們需要的圖片大小和原圖的大小,可以很簡單的求出合適的采樣率:
/**
* 高效的加載圖片(采樣率壓縮方法)
*
* @return
*/
public static Bitmap decodeSampledBitmapFromResurce(Resources res, int resID, int reqWidth, int reqHeight) {
//第一步:將BitmapFactory.Options 的inJustDecodeBounds 參數(shù)設置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;
}