android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解決方案

使用android提供的BitmapFactory解碼一張圖片時产上,有時會遇到該錯誤,即:java.lang.OutOfMemoryError: bitmap size exceeds VM budget仪媒。這往往是由于圖片過大造成的谢鹊。要想正常使用,一種方式是分配更少的內(nèi)存空間來存儲佃扼,即在載入圖片的時候以犧牲圖片質(zhì)量為代價,將圖片進行放縮压昼,這也是不少人現(xiàn)在為避免以上的OOM所采用的解決方法翠订。但是,這種方法是得不償失的尽超,當我們使用圖片作為縮略圖查看時候倒是沒有說什么,但是傲绣,當需要提供圖片質(zhì)量的時候巩踏,該怎么辦呢?java.lang.OutOfMemoryError: bitmap size exceeds VM budget著實讓不少人欲哭無淚呀菠净!前幾天剛好有個需求需要載入SD卡上面的圖片彪杉。

首先是使用

Bitmap bmp = BitmapFactory.decodeFile(pePicFile.getAbsolutePath() +"/"+info.getImage());

上面參數(shù)是我將要讀取的圖片文件及路徑,當文件較小時派近,程序能夠正常運行,但是當我選擇一張大圖時侯嘀,程序立刻蹦出了java.lang.OutOfMemoryError: bitmap size exceeds VM budget的OOM錯誤!

在android設(shè)備上(where you have only 16MB memory available)吠谢,如果使用BitmapFactory解碼一個較大文件诗茎,很大的情況下會出現(xiàn)上述情況。那么错沃,怎么解決枢析?!

先說之前提到過的一種方法:即將載入的圖片縮小司浪,這種方式以犧牲圖片的質(zhì)量為代價把沼。在BitmapFactory中有一個內(nèi)部類BitmapFactory.Options,其中當options.inSampleSize值>1時租谈,根據(jù)文檔:

If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. (1 -> decodes full size; 2 -> decodes 1/4th size; 4 -> decode 1/16th size). Because you rarely need to show and have full size bitmap images on your phone. For manipulations smaller sizes are usually enough.

也就是說捆愁,options.inSampleSize是以2的指數(shù)的倒數(shù)被進行放縮。這樣昼丑,我們可以依靠inSampleSize的值的設(shè)定將圖片放縮載入菩帝,這樣一般情況也就不會出現(xiàn)上述的OOM問題了。現(xiàn)在問題是怎么確定inSampleSize的值呼奢?每張圖片的放縮大小的比例應(yīng)該是不一樣的!這樣的話就要運行時動態(tài)確定州袒。在BitmapFactory.Options中提供了另一個成員inJustDecodeBounds弓候。


3BitmapFactory.Options opts =newBitmapFactory.Options();

opts.inJustDecodeBounds =true;

Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);

設(shè)置inJustDecodeBounds為true后,decodeFile并不分配空間夸研,但可計算出原始圖片的長度和寬度依鸥,即opts.width和opts.height。有了這兩個參數(shù)贱迟,再通過一定的算法,即可得到一個恰當?shù)膇nSampleSize茶敏。Android提供了一種動態(tài)計算的方法缚俏。如下:

publicstaticintcomputeSampleSize(BitmapFactory.Options options,

intminSideLength,intmaxNumOfPixels) {

intinitialSize = computeInitialSampleSize(options, minSideLength,

maxNumOfPixels);

introundedSize;

if(initialSize <=8) {

roundedSize =1;

while(roundedSize < initialSize) {

roundedSize <<=1;

}

}else{

roundedSize = (initialSize +7) /8*8;

}

returnroundedSize;

}

privatestaticintcomputeInitialSampleSize(BitmapFactory.Options options,

intminSideLength,intmaxNumOfPixels) {

doublew = options.outWidth;

doubleh = options.outHeight;

intlowerBound = (maxNumOfPixels == -1) ?1:

(int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));

intupperBound = (minSideLength == -1) ?128:

(int) Math.min(Math.floor(w / minSideLength),

Math.floor(h / minSideLength));

if(upperBound < lowerBound) {

returnlowerBound;

}

if((maxNumOfPixels == -1) &&

(minSideLength == -1)) {

return1;

}elseif(minSideLength == -1) {

returnlowerBound;

}else{

returnupperBound;

}

}

以上參考一下忧换,我們只需要使用此函數(shù)就行了:

BitmapFactory.Options opts =newBitmapFactory.Options();

opts.inJustDecodeBounds =true;

BitmapFactory.decodeFile(imageFile, opts);

opts.inSampleSize = computeSampleSize(opts, -1,128*128);

//這里一定要將其設(shè)置回false,因為之前我們將其設(shè)置成了true

opts.inJustDecodeBounds =false;

try{

Bitmap bmp = BitmapFactory.decodeFile(imageFile, opts);

imageView.setImageBitmap(bmp);

}catch(OutOfMemoryError err) {

}

這樣酪耳,在BitmapFactory.decodeFile執(zhí)行處刹缝,也就不會報出上面的OOM Error了。完美解決赞草?如前面提到的,這種方式在一定程度上是以犧牲圖片質(zhì)量為代價的洲守。如何才能更加優(yōu)化的實現(xiàn)需求沾凄?

當在android設(shè)備中載入較大圖片資源時,可以創(chuàng)建一些臨時空間叙谨,將載入的資源載入到臨時空間中保屯。

2BitmapFactory.Options bfOptions=newBitmapFactory.Options();

bfOptions.inTempStorage=newbyte[12*1024];

以上創(chuàng)建了一個12kb的臨時空間涤垫。然后使用Bitmap bitmapImage = BitmapFactory.decodeFile(path,bfOptions);但是我在程序中卻還是出現(xiàn)以上問題竟终!以下使用BitmapFactory.decodeFileDescriptor解決了以上問題:

BitmapFactory.Options bfOptions=newBitmapFactory.Options();

bfOptions.inDither=false;

bfOptions.inPurgeable=true;

bfOptions.inTempStorage=newbyte[12*1024];

// bfOptions.inJustDecodeBounds = true;

File file =newFile(pePicFile.getAbsolutePath() +"/"+info.getImage());

FileInputStream fs=null;

try{

fs =newFileInputStream(file);

}catch(FileNotFoundException e) {

e.printStackTrace();

}

Bitmap bmp =null;

if(fs !=null)

try{

bmp = BitmapFactory.decodeFileDescriptor(fs.getFD(),null, bfOptions);

}catch(IOException e) {

e.printStackTrace();

}finally{

if(fs!=null) {

try{

fs.close();

}catch(IOException e) {

e.printStackTrace();

}

}

}

當然要將取得圖片進行放縮顯示等處理也可以在以上得到的bmp進行。

PS:請圖片處理后進行內(nèi)存回收榆芦。bmp.recycle();這樣將圖片占有的內(nèi)存資源釋放喘鸟。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末什黑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子兑凿,更是在濱河造成了極大的恐慌,老刑警劉巖咐鹤,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件圣絮,死亡現(xiàn)場離奇詭異,居然都是意外死亡捧请,警方通過查閱死者的電腦和手機棒搜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來可款,“玉大人克蚂,你說我怎么就攤上這事“0龋” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵立镶,是天一觀的道長。 經(jīng)常有香客問我,道長莺奔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任恼琼,我火速辦了婚禮屏富,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘噩死。我一直安慰自己神年,他們只是感情好,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布垛耳。 她就那樣靜靜地躺著飘千,像睡著了一般。 火紅的嫁衣襯著肌膚如雪护奈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天酌予,我揣著相機與錄音奖慌,去河邊找鬼。 笑死建椰,一個胖子當著我的面吹牛岛马,可吹牛的內(nèi)容都是我干的屠列。 我是一名探鬼主播伞矩,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼苛让!你這毒婦竟也來了湿诊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤仿畸,失蹤者是張志新(化名)和其女友劉穎朗和,沒想到半個月后错沽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體眶拉,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡镀层,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吴侦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坞古。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖织堂,靈堂內(nèi)的尸體忽然破棺而出奶陈,到底是詐尸還是另有隱情,我是刑警寧澤吃粒,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站事示,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肖爵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一冀自、第九天 我趴在偏房一處隱蔽的房頂上張望幅聘。 院中可真熱鬧窃植,春花似錦、人聲如沸葛超。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侥涵。三九已至宋雏,卻和暖如春芜飘,著一層夾襖步出監(jiān)牢的瞬間磨总,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工娶牌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留馆纳,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓累榜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親壹罚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容