Bitmapfactory Out of Memory
很多時候,在我們使用BitmapFactory 會產生out of memory的錯誤。因為記憶體對android系統是很寶貴的。所以每一個程式都會限制在一定大小的記憶體裡,只要超過了,系統就會顯示out of memory。通常都會發生在載入圖片的時候。
如果一張2592*1936像素大小的圖片,每一個像素又使用ARGB_8888,那麼他的大小就是19M左右(2592*1936*4 bytes)。這跟圖片格式無關,當程式載入圖片到記憶體中時,就是要恢復成Bitmap去對應螢幕上的每一個像素。所以,如果我們要載入照片,因為現在的照片格式都很大,我們不可能一一去了解照片的格式和大小。就需要用到BitmapFactory.Options的功能。
我們來看看deveolper上的例子。
calculateInSampleSize這個函式就是要從預先得到的BitmapFactory.Options來計算inSampleSize。
如果一張2592*1936像素大小的圖片,每一個像素又使用ARGB_8888,那麼他的大小就是19M左右(2592*1936*4 bytes)。這跟圖片格式無關,當程式載入圖片到記憶體中時,就是要恢復成Bitmap去對應螢幕上的每一個像素。所以,如果我們要載入照片,因為現在的照片格式都很大,我們不可能一一去了解照片的格式和大小。就需要用到BitmapFactory.Options的功能。
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;
這一段程式的內容是利用options.inJustDecodebounds設定為true。如此
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
將會返回一個null值,也就是說圖片將不會被載入記憶體中。而只是讀入圖片的基本資料,如長寬和檔案的類形。等讀入圖形的基本資料後,先預先做處理,再讀入記憶體中,就不容易出現out of memory了。我們來看看deveolper上的例子。
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) { if (width > height) { inSampleSize = Math.round((float)height / (float)reqHeight); } else { inSampleSize = Math.round((float)width / (float)reqWidth); } } return inSampleSize; }
忘了說明option中有一個參數 inSampleSize。這是一個整數。如果為2,就是載入圖片1/2的解析度。如果是3就是載入1/3圖片的解析度。這樣大大的縮小了圖片在記憶體中的大小。很多時候,因為手機解析度的不同,載入一張完整的,不破壞的圖片,不是那麼有意義。calculateInSampleSize這個函式就是要從預先得到的BitmapFactory.Options來計算inSampleSize。
用法如下
final BitmapFactory.Options options = new BitmapFactory.Options();
//先將inJustDecodeBounds設成true,不讓圖片載入記憶體。 options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // 代入calculateInSampleSize計算inSampleSize的大小。
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // 將inJustDecodeBounds設成false,讓圖片載入記憶體。 options.inJustDecodeBounds = false; Bitmap bitmapWeGot=BitmapFactory.decodeResource(res, resId, options);
如此載入記憶體中的bitmapWeGot就會是一個有效利用記憶體的圖片了。
留言
張貼留言