24

以下の問題を正しく解決したことを誰かが確認できるか、または別の解決策があるかどうかを確認していただければ幸いです。

大きな画像 (800*1720 ピクセルなど) をメモリに読み込み、スクロールビューに表示するアプリがあります。画像は博物館の間取り図で、スクロールとズームのようなシンプルな地図が欲しかったのです。イメージは古いデバイスでは正常に読み込まれましたが、Samsung Galaxy S3 ではメモリ不足エラーが発生しました。

LogCat メッセージを見ると、ビットマップの作成時に、800*1720*4 = 5.5MB ではなく、22MB がビットマップに割り当てられていることがわかりました。基本的に、他のデバイスに必要な 4 倍のメモリが割り当てられ、メモリ使用量が 50MB のヒープ サイズを超えていました。

この問題の推奨される解決策は、BitmapFactory.Options.inSampleSizeオプションを使用して、読み込まれた画像の解像度を下げ、必要なメモリを少なくすることです。ただし、これにより画像の品質が低下します。古いデバイスでも問題なく動作するため、実際には元の品質でフルサイズで表示したいと考えています。

頭を悩ませた結果、問題は S3 の WXGA 画面のピクセル密度が 2.0 であるため、画像の各ピクセルに対して、ビットマップが実際には 4 ピクセルを割り当てていることにあると結論付けました。少し試行錯誤して、設定することでこれを防ぐことができることを発見しましたoptions.inScaled = false;

http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inScaled

途中で、 ​​を設定して 4 ピクセルの代わりに 2 ピクセルの忠実度の低い色深度を使用することで、メモリ使用量を半分の 2.7MB に削減できることにも気付きましたoptions.inPreferredConfig = Bitmap.Config.RGB_565;。私のフロアパンでは、これは目に見える画質には影響しませんでした。

したがって、最終的なコードは次のとおりです。

String uri = "drawable/floorplan";
int imageResource = getResources().getIdentifier(uri, null, getPackageName());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inScaled = false;
Bitmap bm = BitmapFactory.decodeResource(getResources(), imageResource, options);
IVfloorplan.setImageBitmap(bm);

このビットマップを表示するときは、元に戻す必要があります。スケーリングを行うには、次からピクセル密度を取得できます。

float density = getResources().getDisplayMetrics().density;

ビットマップのメモリ使用量を 22MB から 2.7MB に削減しました。これは 50MB ヒープではかなりの量です。

4

1 に答える 1

2

S3の画面は本当に高解像度なので、かなり分かりやすいです。また、画像が drawable フォルダーにある場合は、自動的に拡大されている可能性があります。それをオフにする方法があるかもしれません。画像サイズが偶然ではない場合でも、OS は画像を収容するためのバッファーを割り当てる必要があります。また、画面に表示するためのバッファーも割り当てられる可能性があります。

別の方法として、SNES ゲームなどのゲームで使用されるタイリングを使用する方法があります。これは、RAM を使い果たすことなく多くのグラフィックスを処理する方法でもありました。これが、Google マップが地球の地図を持っている方法であることを示す証拠があります。基本的に、大きな画像をタイルに切り刻み、画面にパンするときにタイルを画面に表示します (もちろん、両側に 1 つの余分なタイルがあります)。

これは、Google がビットマップの割り当てをより適切に管理するためのコードを追加したハニカム以降のものですが、ビットマップの割り当てには注意してください。Java プログラムというよりは C プログラムに似ており、C プログラムのように管理することをお勧めします。Android で Bitmap オブジェクトを使用すると、ヒープ領域が不足しやすい

于 2012-10-01T14:18:33.297 に答える