2012-09-29 15 views
24

以下の問題を正しく解決したことを誰かが確認できた場合、または代替ソリューションがある場合は、非常に感謝しますか?Androidビットマップの読み込み中にエラーが発生するGalaxy S3 WXGA

大きな画像(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

を設定することで、この出来事を防ぐことができる発見し、また、私は下の忠実度を使用して2.7メガバイトに半分に私のメモリ使用量を削減することができることを実現しましたoptions.inPreferredConfig = Bitmap.Config.RGB_565;を設定して、4ピクセルの代わりに2ピクセルの色深度を指定します。私のフロアパンでは、これは目に見える画質に影響しませんでした。

最終的なコードは、このようにした:

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; 

を私は22メガバイトから50メガバイトのヒープに重要である2.7メガバイト、ビットマップへのメモリ使用量を削減しました。

+3

良い分析と解決に感謝します。 – Simon

+0

私は、inSampleSizeに関して部分的に同じことを説明しているドキュメンテーションのリンクをここに提供するとよいかもしれないと思う:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html。ビットマップカラーフォーマットとその小道具/小道具で遊ぶことについてhttp://www.curious-creature.org/2010/12/08/bitmap-quality-banding-and-dithering/。 – sandrstar

+0

素晴らしい。私はこれがヒープサイズの小さい他のデバイスでも役立つだろうと考えています。しかし、それはあなたの質問に答える代わりに答えを加えるべきです、それはSOのルールに違反し、 –

答えて

2

S3の画面は本当に高い解像度を持っているので、かなり理解できます。また、画像がドロウアブルフォルダにある場合は、自動的にアップスケールされる可能性があります。それをオフにする方法があるかもしれません。あなたのイメージサイズが偶然でなくても、OSはイメージを格納するバッファを割り当てる必要があります。

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

Googleがビットマップ割り当てをよりよく管理するためにコードを入れているハニカム後のものですが、ビットマップ割り当てには注意してください。それはJavaプログラムよりもCプログラムに似ています。そのように管理することは良い考えです。 Androidでビットマップオブジェクトを使用するときにヒープスペースが不足することは非常に簡単です

関連する問題