2017-09-01 53 views
-2

我正在開發一個解碼jpeg文件並使用canvas.drawBitmap()在畫布上繪製位圖的android應用程序。我正在使用BitmapFactory.decodeStream()將jpeg解碼爲位圖。解碼大位圖時出現OutOfMemoryError

當我使用諸如2560x1536等分辨率的圖像時,一切正常。最近,我做了一個壓力測試,試圖打開一個非常大的分辨率爲5400x3600的jpeg。我的應用程序崩潰,錯誤爲「java.lang.OutOfMemoryError」。

這裏是堆棧跟蹤:

java.lang.OutOfMemoryError 
    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
    at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:720) 
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:696) 
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:734) 
    ... 

這是可以理解的,因爲這是一個大的圖像和解碼的位圖使用了大量的內存。

但是,我想了解的是在同一部手機上,如果使用圖庫應用程序,圖庫應用程序可以顯示相同的大圖像而不會有任何問題。

在同一部手機上,如果我還嘗試用一些圖片編輯工具打開相同的大圖片,我認爲它也應該將jpeg解碼爲位圖,然後一切正常。這些應用需要多一點的時間才能顯示圖像,但圖像會在屏幕上加載和繪製。

我想了解我可能做錯了什麼,與其他應用程序相比有什麼不同?

+1

你的答案就在這裏[鏈接] {} https://stackoverflow.com/questions/25719620/how-to-solve-java-lang-outofmemoryerror-trouble-in-android –

+0

是否將這些圖像存儲在可繪製的文件夾中? – Shruti

+0

歡迎@RichardT –

回答

0

首先,您需要設置

android:largeHeap="true" 

在Android清單。 然後這是幻想,相同大小的圖像顯示在系統庫中。實際上,每個圖書館或圖庫通過保持圖像的高寬比和質量來根據屏幕上的可用尺寸調整圖像的大小。

所以你需要調整你的圖像的大小,然後才能得到大的圖像形成系統。

載入大的位圖高效

讀取的位圖尺寸和類型,

的BitmapFactory類提供了用於創建來自不同源的位圖數解碼方法(decodeByteArray()decodeFile()decodeResource()等)。根據您的圖像數據源選擇最合適的解碼方法。這些方法試圖爲構造的位圖分配內存,因此很容易導致OutOfMemory異常。每種類型的解碼方法都有額外的簽名,可讓您通過BitmapFactory.Options類指定解碼選項。在解碼時將inJustDecodeBounds屬性設置爲true可避免內存分配,對於位圖對象返回null,但設置outWidth,outHeightoutMimeType。該技術允許您在構建位圖之前讀取圖像數據的尺寸和類型(以及內存分配)。

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例外,對其進行解碼,除非你絕對信任來源爲您提供了可用內存內舒適適合預見的大小的圖像數據之前檢查的位圖的尺寸。

將縮小後的版本加載到內存中 既然圖像尺寸是已知的,它們可以用來決定是應該將完整圖像加載到內存中還是應該加載二次採樣版本。以下是一些需要考慮的因素:

在內存中加載完整映像的預計內存使用量。 根據應用程序的其他內存要求,您願意承諾加載此映像的內存量。 圖像要加載到的目標ImageView或UI組件的尺寸。 當前設備的屏幕大小和密度。

See Link

0

OutOfMemoryError

當Java虛擬機無法分配一個對象,因爲 它是內存不足,並沒有更多的內存時可以由 垃圾收集器提供。

確認,新增

<application 
    android:largeHeap="true" 
    > 

爲了避免java.lang.OutOfMemory例外,解碼之前,檢查一個位圖的尺寸,除非你絕對信任來源爲您提供可預測大小的圖像數據舒服適合可用內存。

閱讀Loading Large Bitmaps Efficiently

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); 
} 

該方法可以很容易地任意大尺寸的位圖加載到一個顯示100x100的像素縮略圖的ImageView的,如圖中下面的代碼:

imgOBJ.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100)); 

可以檢查Solve java.lang.OutOfMemoryError trouble in Android

相關問題