2013-06-20 39 views
0

我目前正在製作一個Android應用程序,修改圖像的一些字節。對於這一點,我已經寫了這個代碼:Android:內存友好修改圖像字節

Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(path)); 
ByteBuffer buffer = ByteBuffer.allocate(bmp.getWidth()*bmp.getHeight()); 
bmp.copyPixelsToBuffer(buffer); 
return buffer.array(); 

的問題是,這樣一來佔用過多的堆內存,並拋出OutOfMemoryException。 我知道我可以讓應用程序的堆內存更大,但它似乎不是一個好的設計選擇。

是否有更友善的方式更改圖像的字節?

+2

在這種情況下增加堆可能實際上不是一個糟糕的設計選擇。特別是圖像編輯器需要比普通應用程序更多的堆內存。實際上,這是一個例子,其中使用了較大的堆大小(請參閱Google I/O關於內存管理的講座 - 我認爲它是從2011年開始的)。 – Rarw

+0

'buffer'是一個'ByteBuffer'? – fge

+0

@fge是的,我會將它添加到帖子中。 – Janman

回答

1

它看起來像有託管堆上的像素數據的兩個副本:在ByteBuffer

中數據的Bitmap

  • 複製

    • 未壓縮數據通過將數據保留在位圖中並使用getPixel()/setPixel()(或者可能一次用「批量」變體編輯一行),內存需求可減半,但這會增加一些開銷。

      根據圖像的性質,您可以使用不太精確的格式(例如RGB 565而不是8888),將內存要求減半。

      正如其中一條評論所述,您可以將數據解壓縮到一個文件,使用java.nio.channels.FileChannel#map()進行存儲器映射,然後通過MappedByteBuffer進行訪問。這會給加載和保存增加一些額外的開銷,並且可能很煩人,因爲您必須通過ByteBuffer而不是byte[]

      另一種選擇是擴大堆android:largeHeapdocumented here),雖然在某些方面你只是推遲不可避免的:你可能會被要求編輯一個太大的圖像,而不是「大」的堆。此外,「大型」堆的容量因設備而異,正如「普通大小」堆一樣。這是否合理取決於部分您正在加載的圖像的大小。

      在你做任何事情之前,我建議使用堆分析工具(例如見this blog post)來查看你的內存在哪裏。另外,查看內存不足異常之上的logcat;它應該確定失敗的分配的大小。確保它看起來「合理」,即你不會無意中分配比你想象的更多的東西。