Android面試收集錄15 Android Bitmap壓縮策略

來源:互聯網
上載者:User

標籤:資源   drawable   blog   out   sam   顯示圖片   擷取   idt   led   

 

一、為什麼Bitmap需要高效載入?

現在的高清大圖,動輒就要好幾M,而Android對單個應用所施加的記憶體限制,只有小几十M,如16M,這導致載入Bitmap的時候很容易出現記憶體溢出。如下異常資訊,便是在開發中經常需要的:

java.lang.OutofMemoryError:bitmap size exceeds VM budget

為瞭解決這個問題,就出現了Bitmap的高效載入策略。其實核心思想很簡單。假設通過ImageView來顯示圖片,很多時候ImageView並沒有原始圖片的尺寸那麼大,這個時候把整個圖片載入進來後再設定給ImageView,顯然是沒有必要的,因為ImageView根本沒辦法顯示原始圖片。這時候就可以按一定的採樣率來將圖片縮小後再載入進來,這樣圖片既能在ImageView顯示出來,又能降低記憶體佔用從而在一定程度上避免OOM,提高了Bitmap載入時的效能。

 

 

二、Bitmap高效載入的具體方式1.載入Bitmap的方式

Bitmap在Android中指的是一張圖片。通過BitmapFactory類提供的四類方法:decodeFile,decodeResource,decodeStream和decodeByteArray,分別從檔案系統,資源,輸入資料流和位元組數組中載入出一個Bitmap對象,其中decodeFile,decodeResource又間接調用了decodeStream方法,這四類方法最終是在Android的底層實現的,對應著BitmapFactory類的幾個native方法。

2.BitmapFactory.Options的參數①inSampleSize參數

上述四類方法都支援BitmapFactory.Options參數,而Bitmap的按一定採樣率進行縮放就是通過BitmapFactory.Options參數實現的,主要用到了inSampleSize參數,即採樣率。通過對inSampleSize的設定,對圖片的像素的高和寬進行縮放。

當inSampleSize=1,即採樣後的圖片大小為圖片的原始大小。小於1,也按照1來計算。 當inSampleSize>1,即採樣後的圖片將會縮小,縮放比例為1/(inSampleSize的二次方)。

例如:一張1024 ×1024像素的圖片,採用ARGB8888格式儲存,那麼記憶體大小1024×1024×4=4M。如果inSampleSize=2,那麼採樣後的圖片記憶體大小:512×512×4=1M。

注意:官方文檔支出,inSampleSize的取值應該總是2的指數,如1,2,4,8等。如果外界傳入的inSampleSize的值不為2的指數,那麼系統會向下取整並選擇一個最接近2的指數來代替。比如3,系統會選擇2來代替。當時經驗證明並非在所有Android版本上都成立。

關於inSampleSize取值的注意事項: 通常是根據圖片寬高實際的大小/需要的寬高大小,分別計算出寬和高的縮放比。但應該取其中最小的縮放比,避免縮放圖片太小,到達指定控制項中不能鋪滿,需要展開從而導致模糊。

例如:ImageView的大小是100×100像素,而圖片的原始大小為200×300,那麼寬的縮放比是2,高的縮放比是3。如果最終inSampleSize=2,那麼縮放後的圖片大小100×150,仍然合適ImageView。如果inSampleSize=3,那麼縮放後的圖片大小小於ImageView所期望的大小,這樣圖片就會被展開而導致模糊。

②inJustDecodeBounds參數

我們需要擷取載入的圖片的寬高資訊,然後交給inSampleSize參數選擇縮放比縮放。那麼如何能先不載入圖片卻能獲得圖片的寬高資訊,通過inJustDecodeBounds=true,然後載入圖片就可以實現只解析圖片的寬高資訊,並不會真正的載入圖片,所以這個操作是輕量級的。當擷取了寬高資訊,計算出縮放比後,然後在將inJustDecodeBounds=false,再重新載入圖片,就可以載入縮放後的圖片。

注意:BitmapFactory擷取的圖片寬高資訊和圖片的位置以及程式啟動並執行裝置有關,比如同一張圖片放在不同的drawable目錄下或者程式運行在不同螢幕密度的裝置上,都可能導致BitmapFactory擷取到不同的結果,和Android的資源載入機制有關。

3.高效載入Bitmap的流程

①將BitmapFactory.Options的inJustDecodeBounds參數設為true並載入圖片。

②從BitmapFactory.Options中取出圖片的原始寬高資訊,它們對應於outWidth和outHeight參數。

③根據採樣率的規則並結合目標View的所需大小計算出採樣率inSampleSize。

④將BitmapFactory.Options的inJustDecodeBounds參數設為false,然後重新載入圖片。

 

三、Bitmap高效載入的代碼實現
 public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight){        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        //載入圖片        BitmapFactory.decodeResource(res,resId,options);        //計算縮放比        options.inSampleSize = calculateInSampleSize(options,reqHeight,reqWidth);        //重新載入圖片        options.inJustDecodeBounds =false;        return BitmapFactory.decodeResource(res,resId,options);    }    private static int calculateInSampleSize(BitmapFactory.Options options, int reqHeight, int reqWidth) {        int height = options.outHeight;        int width = options.outWidth;        int inSampleSize = 1;        if(height>reqHeight||width>reqWidth){            int halfHeight = height/2;            int halfWidth = width/2;            //計算縮放比,是2的指數            while((halfHeight/inSampleSize)>=reqHeight&&(halfWidth/inSampleSize)>=reqWidth){                inSampleSize*=2;            }        }        return inSampleSize;    }

 

這個時候就可以通過如下方式高效載入圖片:

mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(),R.mipmap.ic_launcher,100,100);

除了BitmapFactory的decodeResource方法,其他方法也可以類似實現。

 

四、參考文章

  https://github.com/LRH1993/android_interview/blob/master/android/basis/bitmap.md

  

Android面試收集錄15 Android Bitmap壓縮策略

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.