简体   繁体   中英

BitmapFactory.decodeByteArray OutOfMemory

i'm trying to get a Jpeg from Camera.PictureCallback onPictureTaken but when i do this

bitmapImage = BitmapFactory.decodeByteArray(data, 0, data.length);

The first time this is what appears on logcat:

Grow heap (frag case) to 48.886MB for 15728656-byte allocation

And when I try to retake a picture the app crashes with this stack trace:

java.lang.OutOfMemoryError
            at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
            at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:603)
            at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:626)
            at com.delsorboilario.brianzashop.Scatta$5.onPictureTaken(Scatta.java:216)
            at android.hardware.Camera$EventHandler.handleMessage(Camera.java:987)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5511)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
            at dalvik.system.NativeStart.main(Native Method)

this is the code:

android.hardware.Camera.PictureCallback jpegCallback = new android.hardware.Camera.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, android.hardware.Camera camera) {

         bitmapImage = BitmapFactory.decodeByteArray(data, 0, data.length);


        Uri tempUri = getImageUri(getApplicationContext(), bitmapImage);

        File finalFile = new File(getRealPathFromURI(tempUri));

        System.out.println("aaaaaa "+finalFile);


    }
};

EDIT

Following MicheleLacorte's suggest, i'm try to recycle Bitmap after take File finalFile

and its ok but when I try to display image from that path i've the same error.

Loading large bitmaps is really tough in Android look at this

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

Following this http://developer.android.com/training/displaying-bitmaps/load-bitmap.html , I just changed the decodeSampledBitmapFromResource static method to cater for decodeByteArray instead of decodeResource. I put the methods in my util class.

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}    

public static Bitmap decodeSampledBitmapFromResource(byte[] data, int   reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    //options.inPurgeable = true; 
    BitmapFactory.decodeByteArray(data, 0, data.length, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}

Then try this with your code:

android.hardware.Camera.PictureCallback jpegCallback = new  android.hardware.Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, android.hardware.Camera camera) {

     //bitmapImage = BitmapFactory.decodeByteArray(data, 0, data.length);
     // Utils is my utility class
     bitmapImage = Utils.decodeSampledBitmapFromResource(data, 50,50);


    Uri tempUri = getImageUri(getApplicationContext(), bitmapImage);

    File finalFile = new File(getRealPathFromURI(tempUri));

    System.out.println("aaaaaa "+finalFile);


}

};

You say it's when you take a second picture you have problems? Before you allow the user to retake the picture, you need to do something with the first picture to clear up some memory. If you don't intend to continue displaying it, save it to a cache file on disk, and then release your memory resources with

bitmapImage.recycle();
bitmapImage = null;

If you do need to keep it displayed on screen, then downsample it as much as you can without making it look terrible and make sure you're not holding a reference to the original full-size image. Also see if you can do some compression on the image as you get it from the byte array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM