23

BitmapFactory で例外を取得します。何が問題なのかわからない。(まあ、問題は推測できますが、なぜそれが起こっているのかわかりません)

エラー/AndroidRuntime(7906): java.lang.OutOfMemoryError: ビットマップ サイズが VM の予算を超えています

エラー/AndroidRuntime (7906): android.graphics.BitmapFactory.decodeFile (BitmapFactory.java:295) で

私のコードはかなり簡単です。デフォルトの画像を使用して XML レイアウトを定義しました。SDCard に bm をロードしようとします (存在する場合 - 存在します)。そうでない場合は、デフォルトの画像が表示されます。とにかく..コードは次のとおりです。

public class showpicture extends Activity {
  public void onCreate(Bundle savedInstanceState) {

         /** Remove menu/status bar **/
         requestWindowFeature(Window.FEATURE_NO_TITLE);
         final Window win = getWindow();   
         win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

            Bitmap bm;
         super.onCreate(savedInstanceState);
         setContentView(R.layout.showpicture);
            try {
         ImageView mImageButton = (ImageView)findViewById(R.id.displayPicture);
         bm = Bitmap.createScaledBitmap(BitmapFactory.decodeFile("/sdcard/dcim/Camera/20091018203339743.jpg"),100, 100, true);
         parkImageButton.setImageBitmap(bm);
         }
         catch (IllegalArgumentException ex) {
          Log.d("MYAPP",ex.getMessage());
         } 
            catch (IllegalStateException ex) {

bm=Bitmap.createScaledBitmapそれは何か考えに失敗しますか?フォーラムでいくつかの調査を行ったところ、この投稿が指摘されまし たが、なぜ機能しないのかわかりません。どんな助けでも素晴らしいでしょう!ありがとう、

クリス。

4

9 に答える 9

13

inSampleSize は良いヒントです。しかし、ファイルからの大きなビットマップは通常ユーザー ファイルであり、小さなサムネイルからデジカメの 12MP 画像までさまざまであるため、固定値ではうまく機能しないことがよくあります。

これは、迅速でダーティなロード ルーチンです。より良いコード化されたループ、より高速なデコードのために 2 の累乗を使用するなど、改善の余地があることはわかっています。しかし、それは働き始めです...

public static Bitmap loadResizedBitmap( String filename, int width, int height, boolean exact ) {
    Bitmap bitmap = null;
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile( filename, options );
    if ( options.outHeight > 0 && options.outWidth > 0 ) {
        options.inJustDecodeBounds = false;
        options.inSampleSize = 2;
        while (    options.outWidth  / options.inSampleSize > width
                && options.outHeight / options.inSampleSize > height ) {
            options.inSampleSize++;
        }
        options.inSampleSize--;

        bitmap = BitmapFactory.decodeFile( filename, options );
        if ( bitmap != null && exact ) {
            bitmap = Bitmap.createScaledBitmap( bitmap, width, height, false );
        }
    }
    return bitmap;
}

ところで、新しい API には、画像を画面の DPI に合わせるための BitmapFactory.Option もたくさんありますが、それらが本当に何かを簡素化するかどうかはわかりません。android.util.DisplayMetrics.density を使用するか、メモリ消費量を減らすために単に固定サイズを使用すると、よりうまく機能するようです。

于 2010-03-01T14:23:12.767 に答える
4

ビットマップの作成をメモリ不足エラーから保護するようにしてください。ほとんどのプラットフォームでは、Androidには十分なメモリがなく、ビットマップですぐに使い果たされます。また、ビットマップを可能な限り手動でリサイクルするようにしてください。ガベージコレクションがかなり遅くなる可能性があることに気づきました。

try{            
  Bitmap myFragileBitmap = Bitmap.createBitmap(500, 500, Bitmap.Config.ARGB_8888);
}
catch(IllegalArgumentException e){
  Log.e(TAG,"Illegal argument exception.");
}
catch(OutOfMemoryError e){
  Log.e(TAG,"Out of memory error :(");
}
于 2009-10-22T22:02:43.627 に答える
4

問題を解決したように見える次のコードを使用して、ビットマップのサイズを変更しました。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeFile(mPathName, options);
于 2009-10-21T20:21:11.737 に答える
1

これらのオプションは、decodefile で使用します。ビットマップが仮想マシンの予算を超えている問題を解決できることを願っています..

BitmapFactory.Options bfOptions=new BitmapFactory.Options(); 

bfOptions.inDither=false;          //Disable Dithering mode
bfOptions.inPurgeable=true;       //Tell to gc that whether it needs free memory, the Bitmap can be cleared
bfOptions.inInputShareable=true;  //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
bfOptions.inTempStorage=new byte[32 * 1024]; 
于 2011-05-04T04:51:51.300 に答える
0

DDMSをチェックしましたか?Androidは大きな画像をうまく処理しているように見えるので、私が遭遇したことはおそらく画像のサイズではありません. DDMS でヒープをトレースすると、たまたま多くの空きメモリがあることがわかる場合があります。これを追加することで、ヒープを「拡張」できます

static { @SuppressWarnings("unused")
byte dummy[] = new byte[ 8*1024*1024 ]; }    

コードに追加して、ヒープを強制的に拡張します。少し頻度が減るかもしれません。残念ながら、例外を除いて、ある程度のバイトを割り当てることができないと主張しています。1Mと言います。「free」行を見ると、最大のブロックが >> 1M であることがわかります。そこには私には理解できない奇妙なものがあります。画像をスワイプする速度にも関係ありません。ビットマップの「リサイクル」などと呼べるスレッドをいくつか見ました。ヒープサイズが取得したサイズよりもはるかに大きい場合に役立つ理由はまだわかりません。

于 2010-06-14T06:16:41.737 に答える
0

画像のサイズを 320x240 から 64x240 (ダウンスケール) などに変更し始めたときにこのエラーが発生し、プロジェクトにインポートしました (レンダリング速度を改善したかったので、この時点までは役に立たないアルファ領域がたくさん含まれていたためです)。

今、最後の答えは非常に理にかなっています:

この static { @SuppressWarnings("unused") byte dummy[] = new byte[ 8*1024*1024 ]; を追加することで、ヒープを「拡張」できます。} をコードに追加して、ヒープを強制的に拡張します。少し頻度が減るかもしれません。

これが私に起こったことだと思います。Android は自動的にドローアブルをビットマップにデコードします (そして、すべてコンパイル時にヒープに格納されますか?)

実行時にイメージの小さいバージョンを使用すると、エラーが表示され始めました (BitmapFactory.decodeResource と Bitmap.createScaledBitmap を使用して、レトロなグラフィックスで VGA ゲームをプログラムするため、実行時にスケールアップします)。

それは Marve が言ったようでなければなりません: ドローアブル/イメージを縮小してプロジェクトにインポートした後、私の場合、ヒープは十分な大きさではありません。

画像のサイズをより大きなサイズ (320x240) に戻すと、OutOfMemoryException を取り除くことができました。

于 2011-11-14T03:16:11.180 に答える