Bitmap - Out of memory exception

2019-03-01 05:27发布

问题:

When I try to get image from camera or gallery, I get error. Here is a part of logcat:

06-27 05:51:47.297: E/dalvikvm-heap(438): Out of memory on a 35295376-byte allocation.
06-27 05:51:47.312: E/dalvikvm(438): Out of memory: Heap Size=108067KB, Allocated=71442KB, Limit=131072KB
06-27 05:51:47.312: E/dalvikvm(438): Extra info: Footprint=108067KB, Allowed Footprint=108067KB, Trimmed=56296KB
06-27 05:51:47.312: E/PowerManagerService(438): Excessive delay when setting lcd brightness: mLcdLight.setBrightness(176, 1) spend 288ms, mask=2
06-27 05:51:48.052: E/dalvikvm-heap(4332): Out of memory on a 24023056-byte allocation.
06-27 05:51:48.057: E/dalvikvm(4332): Out of memory: Heap Size=63139KB, Allocated=40922KB, Limit=65536KB
06-27 05:51:48.057: E/dalvikvm(4332): Extra info: Footprint=63139KB, Allowed Footprint=63139KB, Trimmed=0KB
06-27 05:51:48.057: E/EmbeddedLogger(438): App crashed! Process: <my_app_name>

Here is my code that provides me to take an image:

Intent pickIntent = new Intent();
pickIntent.setType("image/*");
pickIntent.setAction(Intent.ACTION_GET_CONTENT);

Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

Intent chooserIntent = Intent.createChooser(pickIntent, "Select or take a new Picture");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { takePhotoIntent });
startActivityForResult(chooserIntent, selectPic);

and at onActivityResult() I do:

Bitmap bitmapSelectedImage = null;
Uri selectedImage =  data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };

Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();

String filePath = cursor.getString(cursor.getColumnIndex(filePathColumn[0]));
cursor.close();
bitmapSelectedImage = BitmapFactory.decodeFile(filePath); // Here is where do I get error.

I get error on bitmapSelectedImage = BitmapFactory.decodeFile(filePath); line.

I have looked a lot websites/topics for it but no one could helped.

Any suggestions?

回答1:

your memory allocation heap size is something very limited. trying loading high resolution image from file to the heap can easily cause out of memory error.

assuming that the camera app really taking a very high resolution (almost sure that is the case), you should load to memory only scaled version of the bitmap in the size required for displaying.

the document you already been suggested to see - http://developer.android.com/training/displaying-bitmaps/load-bitmap.html provides full functionall methods to do exactly that.

1) first step is calculating (without loading to memory) the required scale. that's the calculateInSampleSize method.

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) {

        // Calculate ratios of height and width to requested height and
        // width
        final int heightRatio = Math.round((float)height / (float)reqHeight);
        final int widthRatio = Math.round((float)width / (float)reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will
        // guarantee
        // a final image with both dimensions smaller than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
}

2) second step is the full method using step 1:

public static Bitmap getSampleBitmapFromFile(String bitmapFilePath, int reqWidth, int reqHeight) {
    // calculating image size
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(new FileInputStream(new File(bitmapFilePath)), null, options);

    int scale = calculateInSampleSize(options, reqWidth, reqHeight);

    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = scale;

    return BitmapFactory.decodeStream(new FileInputStream(new File(bitmapFilePath)), null, o2);

}

reqHeight and reqWith are the hight and width in pixels of the image view that displaying the image. so let's say your image view is 100x100 pixels, all you need to do is:

bitmapSelectedImage = getSampleBitmapFromFile(filePath, 100, 100);


回答2:

If bitmap sizes are very big or inefficently handled then This problems occurs. To decode bitmap efficiently you can check these tips in android developers site.

Displaying Bitmaps Efficiently



回答3:

Do not use strong references for bitmaps. Use it as below. Always Use weakreferences so that system can gc the object and reduce the memory leaks

WeakReference<Bitmap> bitmapSelectedImage ;


回答4:

You need to scale down your image.

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

Use appropriate Bitmap.decode method and scale down the image.

Bitmap.decode

Example :

Call the method with the required parameters.

public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
 try {
     //Decode image size
     BitmapFactory.Options o = new BitmapFactory.Options();
     o.inJustDecodeBounds = true;
     BitmapFactory.decodeStream(new FileInputStream(f),null,o);

     //The new size we want to scale to
     final int REQUIRED_WIDTH=WIDTH;
     final int REQUIRED_HIGHT=HIGHT;
     //Find the correct scale value. It should be the power of 2.
     int scale=1;
     while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
         scale*=2;

     //Decode with inSampleSize
     BitmapFactory.Options o2 = new BitmapFactory.Options();
     o2.inSampleSize=scale;
     return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
 } catch (FileNotFoundException e) {}
 return null;
}


回答5:

This code worked for me :try this

Bitmap ThumbImage = ThumbnailUtils.extractThumbnail(bitmap, 100, 100);