Android - 保存从相机拍摄的照片,内存不足

时间:2015-08-13 07:33:46

标签: android memory-management bitmap out-of-memory heap-memory

我有一个用例,用户拍照并且图片必须保存在SD卡上。

我已将相机的方向设置为肖像。

s aving the photo on to SD card我正在out of memory

这是日志 -

java.lang.RuntimeException: An error occured while executing doInBackground()
  at android.os.AsyncTask$3.done(AsyncTask.java:300)
  at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
  at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
  at java.util.concurrent.FutureTask.run(FutureTask.java:242)
  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
  at java.lang.Thread.run(Thread.java:841)
Caused by: java.lang.OutOfMemoryError
  at android.graphics.Bitmap.nativeCreate(Native Method)
  at android.graphics.Bitmap.createBitmap(Bitmap.java:809)
  at android.graphics.Bitmap.createBitmap(Bitmap.java:786)
  at android.graphics.Bitmap.createBitmap(Bitmap.java:718)
  at com.philips.cl.di.haircare.util.AppUtility.changeOrientationAndwriteDataToFile(AppUtility.java:382)
  at com.philips.cl.di.haircare.mirror.MirrorCameraViewFragment$SaveBitMap.doInBackground(MirrorCameraViewFragment.java:389)
  at com.philips.cl.di.haircare.mirror.MirrorCameraViewFragment$SaveBitMap.doInBackground(MirrorCameraViewFragment.java:369)
  at android.os.AsyncTask$2.call(AsyncTask.java:288)
  at java.util.concurrent.FutureTask.run(FutureTask.java:237)
  ... 4 more

这是我用来保存的功能 -

public static boolean changeOrientationAndwriteDataToFile(Context context,
        final File pictureFile, final byte[] data, final int camId)
        throws Exception {

    FileOutputStream fos = null;
    Bitmap realImage = null;
    try {

        fos = new FileOutputStream(pictureFile);
        realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(camId, info);
        Matrix matrix = new Matrix();

        int rotation = info.orientation;
        int camfacing = info.facing;

        if (camfacing == 1) {
            matrix.setScale(1, -1);
        }
        if (rotation != 0) {
            matrix.postRotate(rotation);

        } else {
            matrix.postRotate(-90);
        }
        realImage = Bitmap.createBitmap(realImage, 0, 0,
                realImage.getWidth(), realImage.getHeight(), matrix, false);
        MediaScannerConnection.scanFile(context,
                new String[] { pictureFile.getPath() },
                new String[] { "image/jpeg" }, null);

        // 100 means maximum quality
        return realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
    } catch (final Exception e) {
        throw e;

    } finally {
        if (realImage != null) {
            realImage.recycle();
        }
        if (fos != null) {
            fos.close();
        }
    }

}

行号 - 382内存不足。

realImage = Bitmap.createBitmap(realImage, 0, 0,
                realImage.getWidth(), realImage.getHeight(), matrix, false);

请帮忙解决此问题。

感谢。

3 个答案:

答案 0 :(得分:3)

我使用extension UIAlertController { open override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return UIInterfaceOrientationMask.portrait } open override var shouldAutorotate: Bool { return false } } 解决了它 这是更新的方法 -

,

此处 - BitmapFactory Optionspublic static boolean changeOrientationAndwriteDataToFile(Context context, final File pictureFile, final byte[] data, final int camId, int reqWidth , int reqHeight ) throws Exception { FileOutputStream fos = null; Bitmap realImage = null; Bitmap transformedImage = null ; try { android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(camId, info); int rotation = info.orientation; int camfacing = info.facing; // Out of memory issue fixx -with the sample size concept BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true ; BitmapFactory.decodeByteArray(data, 0, data.length, options); options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight); System.out.println("Sample Size : " + options.inSampleSize); options.inPreferredConfig = Bitmap.Config.RGB_565; options.inJustDecodeBounds = false; realImage= BitmapFactory.decodeByteArray(data, 0, data.length, options); Matrix matrix = new Matrix(); if (camfacing == 1) { matrix.setScale(1, -1); } if (rotation != 0) { matrix.postRotate(rotation); } else { matrix.postRotate(-90); } transformedImage = Bitmap.createBitmap(realImage, 0, 0, realImage.getWidth(), realImage.getHeight(), matrix, false); MediaScannerConnection.scanFile(context, new String[] { pictureFile.getPath() }, new String[] { "image/jpeg" }, null); fos = new FileOutputStream(pictureFile); // 100 means maximum quality return transformedImage.compress(Bitmap.CompressFormat.JPEG, 100, fos); } catch (final Exception e) { throw e; } finally { if (realImage != null) { realImage.recycle(); } if(transformedImage !=null) { transformedImage.recycle(); } if (fos != null) { fos.close(); } } } reqWidthreqHeight,因为我必须在整个屏幕上显示位图。

感谢。

答案 1 :(得分:0)

您可以将android:largeHeap="true"添加到AndroidManifest.xml

这是一种解决方法。小心使用。

答案 2 :(得分:0)

制作新的位图对象,而不是重新创建realImage