6

ではonPictureTaken、次のことを行います。

Bitmap decodedPicture = BitmapFactory.decodeByteArray(data, 0, data.length);
Matrix matrix = new Matrix();
matrix.preScale(-1.0f, 1.0f);
Bitmap picture = Bitmap.createBitmap(decodedPicture, 0, 0, decodedPicture.getWidth(), decodedPicture.getHeight(), matrix, false);

View v1 = mainLayout.getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap screenshot = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);

Bitmap scaledPicture = Bitmap.createScaledBitmap(picture, screenshot.getWidth(), screenshot.getHeight(), true);

Bitmap compos = Bitmap.createBitmap(scaledPicture.getWidth(), scaledPicture.getHeight(), Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(compos);
canvas.drawBitmap(scaledPicture, new Matrix(), null);
canvas.drawBitmap(screenshot, new Matrix(), null);

MediaStore.Images.Media.insertImage(getContentResolver(), compos, "name" , "description");
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));

私の唯一の要件は、高品質の写真を保存したいということです...それを犠牲にしなければならないかもしれません.

私の Nexus 4 以降のデバイスでは、このコードは正常に動作し、期待どおりに動作します。しかし、メモリが少ない古いデバイスでは、RAM が不足しています! :(

メモリ制限に達することなく同じ画像操作を行うにはどうすればよいですか?? これらの画像を画面に表示しようとしているわけではないので、縮小された画像に関係する解決策はここでは実際には当てはまりません...

4

4 に答える 4

3

サンプルサイズを増やしてビットマップを読み込む必要があります。コツは、最終的に画像を拡大縮小したときに解像度が低下しない正しいサンプル サイズを見つけることです。スケーリング用の優れたユーティリティ クラスを含むブログ エントリをここに書きました。

http://zerocredibility.wordpress.com/2011/01/27/android-bitmap-scaling/

特定のニーズに応じて、おそらくそのクラスをかなり単純化できます。

要点は、ビットマップのサイズだけを読み取ることです。目的のスケーリングされたサイズに基づいて最適なサンプル サイズを計算し、そのサンプル サイズを使用してビットマップを読み取り、必要なサイズに正確にスケーリングします。

于 2013-04-29T17:40:18.343 に答える
0

非常に多くの Bitmap オブジェクトが横たわっています。これのいくつかをリサイクル/再利用してみてください。

あなたの要件が何であるか正確にはわかりませんが、これを行うだけでメモリを節約できることがわかります。

        Bitmap decodedPicture = BitmapFactory.decodeByteArray(data, 0, data.length);
        Matrix matrix = new Matrix();
        matrix.preScale(-1.0f, 1.0f);
        Bitmap picture = Bitmap.createBitmap(decodedPicture, 0, 0, decodedPicture.getWidth(), decodedPicture.getHeight(), matrix, false);

        decodedPicture.recycle();
        decodedPicture=null;

        View v1 = mainLayout.getRootView();
        v1.setDrawingCacheEnabled(true);
        Bitmap screenshot = Bitmap.createBitmap(v1.getDrawingCache());
        v1.setDrawingCacheEnabled(false);

        Bitmap scaledPicture = Bitmap.createScaledBitmap(picture, screenshot.getWidth(), screenshot.getHeight(), true);

        picture.recycle();
        picture=null;

        Bitmap compos = Bitmap.createBitmap(scaledPicture.getWidth(), scaledPicture.getHeight(), Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(compos);
        canvas.drawBitmap(scaledPicture, new Matrix(), null);
        canvas.drawBitmap(screenshot, new Matrix(), null);

        MediaStore.Images.Media.insertImage(getContentResolver(), compos, "name" , "description");
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));

また、メモリフットプリントを調べて、使用しているデバイスごとのメモリが大きすぎないことを確認してください。

参考までに、ポスト ハニカム デバイスでは、ネイティブ レイヤーに割り当てられたビットマップ ピクセル イメージ。メモリを復元する必要がありrecycle()ますfinalizer()

于 2013-04-29T17:47:46.867 に答える
0

ビットマップのサイズを変更したくないし、表示したくないことを考えると、私は次のようにします:

  1. ビットマップをロードしてinJustDecodeBounds、元の高さと幅を確認します (コードはhereから)

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);
    
    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    
  2. 持っているサイズとメモリに応じて、そこから直接処理する (つまり、ビットマップをロードする) か、データのチャンクのみをロードできるBitmap.createBitmapメソッドを使用して、前述のビットマップのいくつかのチャンクをロードすることができます。recycle()オプション:チャンクを処理する前に、バイト配列 (以下のコードを参照) と null+ に変換することを検討してください。

コード

ByteArrayOutputStream byteArrayBitmapStream = new ByteArrayOutputStream();
bitmapPicture.compress(Bitmap.CompressFormat.PNG, COMPRESSION_QUALITY, byteArrayBitmapStream);
byte[] b = byteArrayBitmapStream.toByteArray();
于 2013-04-29T17:50:26.207 に答える