Bitmap Out Of Memory Issues

后端 未结 3 1443
一整个雨季
一整个雨季 2020-12-18 07:49

My Problem

I take a picture with my android device. I then decode that picture from file.

        Bitmap photo = BitmapFactory.deco         


        
相关标签:
3条回答
  • 2020-12-18 08:19

    Here is a more complete example of how to resize/rotate, taken in part from the Android Developers guide (change REQ_WIDTH and REQ_HEIGHT):

    private static final int REQ_WIDTH = 450;
    private static final int REQ_HEIGHT = 450;
    
    /**
     * Resize, crop, rotate and Inserts the picture on the layout.
     * 
     * @param mImageView to insert the bitmap.
     * @param imageURI from wich to obtain the bitmap.
     * 
     */
    private void setPic(ImageView mImageView, String imageURI) {
        // Get the original bitmap dimensions
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(imageURI, options);
    
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, REQ_HEIGHT, REQ_WIDTH);
    
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeFile(imageURI, options);
    
        //need rotation?
        float rotation = rotationForImage(getActivity(), Uri.fromFile(new File(imageURI)));
    
        if (rotation != 0) {
            //rotate
            Matrix matrix = new Matrix();
            matrix.preRotate(rotation);
            mImageView.setImageBitmap(Bitmap.createBitmap(bitmap, 0, 0, REQ_HEIGHT, REQ_WIDTH, matrix, true));
        } else {
            //use the original
            mImageView.setImageBitmap(BitmapFactory.decodeFile(imageURI, options));
        }
    }
    
    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) {
            if (width > height) {
                inSampleSize = Math.round((float) height / (float) reqHeight);
            } else {
                inSampleSize = Math.round((float) width / (float) reqWidth);
            }
        }
        return inSampleSize;
    }
    
    public static float rotationForImage(Context context, Uri uri) {
        try {
            if (uri.getScheme().equals("content")) {
                String[] projection = { Images.ImageColumns.ORIENTATION };
                Cursor c = context.getContentResolver().query(uri, projection, null, null, null);
                if (c.moveToFirst()) {
                    return c.getInt(0);
                }
            } else if (uri.getScheme().equals("file")) {
                ExifInterface exif = new ExifInterface(uri.getPath());
                int rotation = (int) exifOrientationToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL));
                return rotation;
            }
            return 0;
    
        } catch (IOException e) {
            Log.e(TAG, "Error checking exif", e);
            return 0;
        }
    }
    
    private static float exifOrientationToDegrees(int exifOrientation) {
        if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
            return 90;
        } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
            return 180;
        } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
            return 270;
        }
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-18 08:30

    For out of memory issue

    //decodes image and scales it to reduce memory consumption

    private Bitmap decodeFile(File f){
    
    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_SIZE=70;
    
        //Find the correct scale value. It should be the power of 2.
        int scale=1;
        while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
            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;
    }
    
    0 讨论(0)
  • 2020-12-18 08:35

    I had the exact same issue, doing the exact same thing on the exact same device! Unfortunately in my case the image needed to be submitted to a webservice, using the full size, original. What worked for me was turning on largeHeap in the application element of the manifest.

    This will not solve the issue permanently - its possible that a device will come along with an even larger camera and the images will not fit in memory even with largeHeap enabled. To catch this extreme edge case I also put a try catch around the code that rotates the image, and just displayed a nice error to the user.

    A fuller solution would be to write your own jpeg manipulation code that can rotate a jpeg using a stream based approach so that the image never needs to be loaded into memory.

    0 讨论(0)
提交回复
热议问题