0

Webストリームからビットマップをデコードしようとしているときに、ビットマップのエクステントが許可されているメモリサイズを超えた場合に、アプリがクラッシュすることがあります。

これを克服するために、私はここで説明されている戦略を使用しています:

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

幅と高さを500x500の慎重なアプローチをcalculateInSampleSizeの入力として使用しているため、メモリの問題は発生しなくなりましたが、ダウンスケールされた画像の画質が悪いとお客様から苦情が寄せられています。

クラッシュしないビットマップエクステントを決定する明確な方法がないように思われるため、残念ながら、かなり低い値(ここでは500x500)で試してみる必要がありますが、具体的なケースでは1000x1000でも問題なく動作します。

calculateInSampleSizeの入力としてどのビットマップエクステントが最大エクステントであるかを確認する方法はありますか?これは、decodeByteArrayなどの後続の呼び出しでアプリをクラッシュさせませんか?

よろしく

4

1 に答える 1

1

OK、方法を見つけました。私はここでそれを共有するのが好きです、多分いくつかの賛否両論があります。

1)最初に(元のコードから変更されていません)、関数に対してbyte[]で使用できるビットマップの元の範囲を決定しています。

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, options);

    /* Here we have the original dimensions of the bitmap */
    int iH = options.outHeight;
    int iW = options.outWidth;
    String iT = options.outMimeType;

2)次に、最適なスケーリング値を見つけようとしています。これは、最終的に2048x2048以下のビットマップを生成します。これはOpenGLの制限のようです(少なくともトレースはそのようなことを教えてくれます)。

    int rh = iH;
    int rw = iW;
    int sz = 1;

    while (true) {
        rh = Math.round((float)iH/(float)(sz));
        rw = Math.round((float)iW/(float)(sz));
        if (rh <= 2048 && rw <= 2048)
            break;
        sz++;
    } 

3)最後に、新しい(おそらくダウンスケールされたイメージ)を作成し、ここでもメモリオーバーフローエラーの可能性をキャッチしようとしています。そのとき、szへの正のデルタを増やして繰り返すことができましたが、nullを返すことにしました。

    options.inJustDecodeBounds = false;
    options.inSampleSize = sz;
    Bitmap bm = null;
    try {
        bm = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, options);
    }
    catch (OutOfMemoryError e) {
    }
    return bm;

それは私にとってはうまくいきます。

于 2013-03-15T09:37:04.420 に答える