一、什麼是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;
}
}