以下の問題を正しく解決したことを誰かが確認できるか、または別の解決策があるかどうかを確認していただければ幸いです。
大きな画像 (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 ヒープではかなりの量です。