0

現在、画像の一部のバイトを変更する Android アプリを作成しています。このために、私はこのコードを書きました:

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

問題は、この方法があまりにも多くのヒープ メモリを使用し、OutOfMemoryException. アプリのヒープ メモリを大きくできることはわかっていますが、それは適切な設計上の選択ではないようです。

画像のバイトを変更する、よりメモリに優しい方法はありますか?

4

1 に答える 1

1

マネージ ヒープにピクセル データのコピーが 2 つあるようです。

  • 圧縮されていないデータBitmap
  • 内のデータのコピーByteBuffer

ビットマップにデータを残してgetPixel()/を使用するsetPixel()(または「一括」バリアントを使用して一度に行を編集する) ことにより、メモリ要件を半分にすることができますが、オーバーヘッドが追加されます。

画像の性質によっては、精度の低い形式 (8888 の代わりに RGB 565 など) を使用して、メモリ要件を半分にできる場合があります。

コメントの 1 つに記載されているように、データをファイルに解凍し、 でメモリ マップしjava.nio.channels.FileChannel#map()MappedByteBuffer. これにより、読み込みと保存にかなりのオーバーヘッドが追加されByteBufferbyte[].

別のオプションは、ヒープを拡張することですandroid:largeHeap(ここに文書化されています)。ただし、いくつかの点では避けられないことを延期しているだけです:「大きな」ヒープには大きすぎる画像を編集するように求められる場合があります。また、「通常サイズ」ヒープと同様に、「大」ヒープの容量はデバイスごとに異なります。これが理にかなっているかどうかは、読み込んでいる画像の大きさに部分的に依存します。

これを行う前に、ヒープ分析ツール (たとえば、このブログ投稿を参照) を使用して、メモリがどこに向かっているのかを確認することをお勧めします。また、メモリ不足の例外の上の logcat を見てください。失敗した割り当てのサイズを特定する必要があります。「合理的」に見えることを確認してください。つまり、自分が思っているよりもかなり多くを誤って割り当てていないことを確認してください。

于 2013-06-20T20:39:25.660 に答える