Bitmap高效加載圖片

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章