2015-12-22 50 views
1

我基本上是試圖壓縮,並通過由然而用戶在不同的手機使用的OutOfMemoryError問題的應用程序崩潰選定的圖像的Base64表示。這裏是我的壓縮和轉換代碼:Android的位圖壓縮不足,導致OutOfMemoryError異常崩潰

Bitmap bm = BitmapFactory.decodeFile(filePath); 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); 
byte[] byteArrayImage = baos.toByteArray(); 
String base64String = Base64.encodeToString(byteArrayImage, Base64.DEFAULT); 

這個過程也是十分緩慢,並導致應用程序有時會崩潰。

這裏有一個例外,我得到了:

java.lang.OutOfMemoryError: Failed to allocate a 5035548 byte allocation with 5011320 free bytes and 4MB until OOM 
    at dalvik.system.VMRuntime.newNonMovableArray(Native Method) 
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:625) 
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:460) 
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:973) 
    at android.content.res.Resources.loadDrawableForCookie(Resources.java:2477) 

我應該做什麼樣的變化?

回答

2
final BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = true; 
options.inSampleSize = 2; //you can also calculate your inSampleSize 
options.inJustDecodeBounds = false; 
options.inTempStorage = new byte[16 * 1024]; 

Bitmap bm = BitmapFactory.decodeFile(filePath,options); //changed line code 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); 
byte[] byteArrayImage = baos.toByteArray(); 
String base64String = Base64.encodeToString(byteArrayImage, Base64.DEFAULT); 

注:使用android:largeHeap="true"爲您的應用程序不被認爲是一個理想的解決方案。

下面是來自谷歌的提取物來解釋它,

然而,要求一大堆的能力僅用於一 小集合的應用程序,可以證明需要消耗更多的RAM(例如 作爲一個大型照片編輯應用程序)。從來沒有要求一大堆只是 因爲你已經用完了內存,你需要速戰速決,你應該 使用它,只有當你確切地知道你所有的內存被分配 以及爲什麼必須保留。但是,即使您對自己的應用程序有足夠的信心,也可以在任何可能的範圍內儘可能避免向 發送請求。使用額外的內存將越來越多地損害整體用戶體驗,因爲垃圾收集將花費更長的時間,並且當任務切換或執行其他常見操作時,系統性能可能會更慢。

這裏的文檔的完整鏈接https://developer.android.com/training/articles/memory.html

編輯1:對於非常大的圖片對於像WhatsApp的圖像壓縮圖像結賬的高效靈活,這SO Answer

+0

感謝您的詳細解釋。使用此解決方案壓縮後輸出圖像的質量如何?它受到很大影響嗎? – Dinuka

+0

在平均圖像上看起來不錯,但圖像越高,需要的時間就越長。我們可以加快這一點嗎? – Dinuka

+0

是的,你可以爲此你必須縮放圖像。看看'Edit 1'。 –

0

嘗試使用後回收您的位圖。並將位圖也設置爲null。如果你想運行垃圾收集器。

+0

你能告訴我代碼嗎?我沒有做過 – Dinuka

+0

bm.recycle(); BM = NULL;系統。GC(); – ajantha

0

這種方法不會很好地工作,說從照相機拍攝的照片。一張13mp的照片是4128x3096x3字節,大約40兆字節。這就是單獨的位圖的大小。如果正在對飛創建基-64表示,這將需要另外的40兆和更多一些,則由於基底-64串花費更多個字節來存儲比相當的原始字節陣列(位圖)。

你真的需要把它變成基礎64嗎?如果你想上傳它,你可以直接通過rest api或多部分發布請求來完成。

,如果你不能這樣做,也許你可以每1 MB拆分操作,如,或替代書寫字符串到內存中,你可以把它寫到文件,並每隔1 MB術後追加呢?

+0

您認爲哪種解決方案更好?多部分上傳或Base64? Facebook,Instagram等使用哪種方法? – Dinuka

+1

@Earthling'Multipart'是更好的上傳圖像的解決方案,使用'base64'將圖像轉換爲字符串將其尺寸增加** 33%**,從而帶來更多帶寬。 –

+0

@VipulAsri你有什麼資料可以找?我需要通過休息服務發佈上傳 – Dinuka