W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
編寫:kesenhoo - 原文:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
圖片有不同的形狀與大小。在大多數(shù)情況下它們的實(shí)際大小都比需要呈現(xiàn)的尺寸大很多。例如,系統(tǒng)的圖庫(kù)應(yīng)用會(huì)顯示那些我們使用相機(jī)拍攝的照片,但是那些圖片的分辨率通常都比設(shè)備屏幕的分辨率要高很多。
考慮到應(yīng)用是在有限的內(nèi)存下工作的,理想情況是我們只需要在內(nèi)存中加載一個(gè)低分辨率的照片即可。為了更便于顯示,這個(gè)低分辨率的照片應(yīng)該是與其對(duì)應(yīng)的UI控件大小相匹配的。加載一個(gè)超過屏幕分辨率的高分辨率照片不僅沒有任何顯而易見的好處,還會(huì)占用寶貴的內(nèi)存資源,另外在快速滑動(dòng)圖片時(shí)容易產(chǎn)生額外的效率問題。
這一課會(huì)介紹如何通過加載一個(gè)縮小版本的圖片,從而避免超出程序的內(nèi)存限制。
BitmapFactory提供了一些解碼(decode)的方法(decodeByteArray(), decodeFile(), decodeResource()等),用來從不同的資源中創(chuàng)建一個(gè)Bitmap。 我們應(yīng)該根據(jù)圖片的數(shù)據(jù)源來選擇合適的解碼方法。 這些方法在構(gòu)造位圖的時(shí)候會(huì)嘗試分配內(nèi)存,因此會(huì)容易導(dǎo)致OutOfMemory
的異常。每一種解碼方法都可以通過BitmapFactory.Options設(shè)置一些附加的標(biāo)記,以此來指定解碼選項(xiàng)。設(shè)置 inJustDecodeBounds 屬性為true
可以在解碼的時(shí)候避免內(nèi)存的分配,它會(huì)返回一個(gè)null
的Bitmap,但是可以獲取到 outWidth, outHeight 與 outMimeType。該技術(shù)可以允許你在構(gòu)造Bitmap之前優(yōu)先讀圖片的尺寸與類型。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
為了避免java.lang.OutOfMemory
的異常,我們需要在真正解析圖片之前檢查它的尺寸(除非你能確定這個(gè)數(shù)據(jù)源提供了準(zhǔn)確無誤的圖片且不會(huì)導(dǎo)致占用過多的內(nèi)存)。
通過上面的步驟我們已經(jīng)獲取到了圖片的尺寸,這些數(shù)據(jù)可以用來幫助我們決定應(yīng)該加載整個(gè)圖片到內(nèi)存中還是加載一個(gè)縮小的版本。有下面一些因素需要考慮:
例如,如果把一個(gè)大小為1024x768像素的圖片顯示到大小為128x96像素的ImageView上嗎,就沒有必要把整張?jiān)瓐D都加載到內(nèi)存中。
為了告訴解碼器去加載一個(gè)縮小版本的圖片到內(nèi)存中,需要在BitmapFactory.Options 中設(shè)置 inSampleSize 的值。例如, 一個(gè)分辨率為2048x1536的圖片,如果設(shè)置 inSampleSize 為4,那么會(huì)產(chǎn)出一個(gè)大約512x384大小的Bitmap。加載這張縮小的圖片僅僅使用大概0.75MB的內(nèi)存,如果是加載完整尺寸的圖片,那么大概需要花費(fèi)12MB(前提都是Bitmap的配置是 ARGB_8888)。下面有一段根據(jù)目標(biāo)圖片大小來計(jì)算Sample圖片大小的代碼示例:
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
Note: 設(shè)置inSampleSize為2的冪是因?yàn)榻獯a器最終還是會(huì)對(duì)非2的冪的數(shù)進(jìn)行向下處理,獲取到最靠近2的冪的數(shù)。詳情參考inSampleSize的文檔。
為了使用該方法,首先需要設(shè)置 inJustDecodeBounds 為 true
, 把options的值傳遞過來,然后設(shè)置 inSampleSize 的值并設(shè)置 inJustDecodeBounds 為 false
,之后重新調(diào)用相關(guān)的解碼方法。
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
使用上面這個(gè)方法可以簡(jiǎn)單地加載一張任意大小的圖片。如下面的代碼樣例顯示了一個(gè)接近 100x100像素的縮略圖:
mImageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
我們可以通過替換合適的BitmapFactory.decode* 方法來實(shí)現(xiàn)一個(gè)類似的方法,從其他的數(shù)據(jù)源解析Bitmap。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: