AndroidBitmap壓縮策略

一、為什么Bitmap需要高效加載?

現(xiàn)在的高清大圖,動輒就要好幾M,而Android對單個應(yīng)用所施加的內(nèi)存限制,只有
小幾十M,如16M,這導(dǎo)致加載Bitmap的時候很容易出現(xiàn)內(nèi)存溢出。如下異常信
息,便是在開發(fā)中經(jīng)常需要的:

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了德安免費(fèi)建站歡迎大家使用!

java.lang.OutofMemoryError:bitmap size exceeds VM budget

為了解決這個問題,就出現(xiàn)了Bitmap的高效加載策略。其實(shí)核心思想很簡單。假設(shè)
通過ImageView來顯示圖片,很多時候ImageView并沒有原始圖片的尺寸那么大,
這個時候把整個圖片加載進(jìn)來后再設(shè)置給ImageView,顯然是沒有必要的,因?yàn)?br/>ImageView根本沒辦法顯示原始圖片。這時候就可以按一定的采樣率來將圖片縮小
后再加載進(jìn)來,這樣圖片既能在ImageView顯示出來,又能降低內(nèi)存占用從而在一
定程度上避免OOM,提高了Bitmap加載時的性能

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

Bitmap在Android中指的是一張圖片。通過BitmapFactory類提供的四類方法:
decodeFile,decodeResource,decodeStreamdecodeByteArray,分別從文件系統(tǒng),
資源,輸入流和字節(jié)數(shù)組中加載出一個Bitmap對象,其中
decodeFile,decodeResource又間接調(diào)用了decodeStream方法,這四類方法最終是
在Android的底層實(shí)現(xiàn)的,對應(yīng)著BitmapFactory類的幾個native方法。

2.BitmapFactory.Options的參數(shù)

inSampleSize參數(shù)
上述四類方法都支持BitmapFactory.Options參數(shù),而Bitmap的按一定采樣率進(jìn)行縮
放就是通過BitmapFactory.Options參數(shù)實(shí)現(xiàn)的,主要用到了inSampleSize參數(shù),即
采樣率。通過對inSampleSize的設(shè)置,對圖片的像素的高和寬進(jìn)行縮放。

當(dāng)inSampleSize=1,即采樣后的圖片大小為圖片的原始大小。小于1,也按照1來計(jì)
算。 當(dāng)inSampleSize>1,即采樣后的圖片將會縮小,縮放比例為1/(inSampleSize
的二次方)。

例如:一張1024 ×1024像素的圖片,采用ARGB8888格式存儲,那么內(nèi)存大小
1024×1024×4=4M。如果inSampleSize=2,那么采樣后的圖片內(nèi)存大?。?br/>512×512×4=1M。

注意:官方文檔支出,inSampleSize的取值應(yīng)該總是2的指數(shù),如1,2,4,8等。
如果外界傳入的inSampleSize的值不為2的指數(shù),那么系統(tǒng)會向下取整并選擇一個
最接近2的指數(shù)來代替。比如3,系統(tǒng)會選擇2來代替。當(dāng)時經(jīng)驗(yàn)證明并非在所有
Android版本上都成立。

關(guān)于inSampleSize取值的注意事項(xiàng): 通常是根據(jù)圖片寬高實(shí)際的大小/需要的寬高
大小,分別計(jì)算出寬和高的縮放比。但應(yīng)該取其中最小的縮放比,避免縮放圖片太
小,到達(dá)指定控件中不能鋪滿,需要拉伸從而導(dǎo)致模糊。

例如:ImageView的大小是100×100像素,而圖片的原始大小為200×300,那么寬
的縮放比是2,高的縮放比是3。如果最終inSampleSize=2,那么縮放后的圖片大小
100×150,仍然合適ImageView。如果inSampleSize=3,那么縮放后的圖片大小小
ImageView所期望的大小,這樣圖片就會被拉伸而導(dǎo)致模糊。

inJustDecodeBounds參數(shù)
我們需要獲取加載的圖片的寬高信息,然后交給inSampleSize參數(shù)選擇縮放比縮
放。那么如何能先不加載圖片卻能獲得圖片的寬高信息,通過
inJustDecodeBounds=true,然后加載圖片就可以實(shí)現(xiàn)只解析圖片的寬高信息,并
不會真正的加載圖片,所以這個操作是輕量級的。當(dāng)獲取了寬高信息,計(jì)算出縮放
比后,然后在將inJustDecodeBounds=false,再重新加載圖片,就可以加載縮放后
的圖片。

注意:BitmapFactory獲取的圖片寬高信息和圖片的位置以及程序運(yùn)行的設(shè)備有
關(guān),比如同一張圖片放在不同的drawable目錄下或者程序運(yùn)行在不同屏幕密度的設(shè)
備上,都可能導(dǎo)致BitmapFactory獲取到不同的結(jié)果,和Android的資源加載機(jī)制
有關(guān)

3.高效加載Bitmap的流程

①將BitmapFactory.OptionsinJustDecodeBounds參數(shù)設(shè)為true并加載圖片。
②從BitmapFactory.Options中取出圖片的原始寬高信息,它們對應(yīng)于outWidth
outHeight參數(shù)。

③根據(jù)采樣率的規(guī)則并結(jié)合目標(biāo)View的所需大小計(jì)算出采樣率inSampleSize。
④將BitmapFactory.OptionsinJustDecodeBounds參數(shù)設(shè)為false,然后重新加載
圖片。

三、Bitmap高效加載的代碼實(shí)現(xiàn)
  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);
     //計(jì)算縮放比
     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;
         //計(jì)算縮放比,是2的指數(shù)
         while((halfHeight/inSampleSize)>=reqHeight&&(halfWidth/inSampleSize)>=reqWidth){
               inSampleSize*=2;
         }
     }

     return inSampleSize;
  }

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

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

除了BitmapFactorydecodeResource方法,其他方法也可以類似實(shí)現(xiàn)。

更多內(nèi)容詳情請關(guān)注我的GitHub:https://github.com/xiangjiana/Android-MS

本文標(biāo)題:AndroidBitmap壓縮策略
文章出自:http://muchs.cn/article12/pdpigc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站、搜索引擎優(yōu)化網(wǎng)站策劃、網(wǎng)站設(shè)計(jì)全網(wǎng)營銷推廣、軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化