Skip to content Skip to sidebar Skip to footer

Problem With Big Images ( Java.lang.outofmemoryerror: Bitmap Size Exceeds Vm Budget )

as a many people i have a problem with big images too. ok,here my code. I found on stackoverflow how to fix this using BitmapFactory.Options. But in my situations i get image no

Solution 1:

since you are getting image from camera,get the uri of the image you capture in onActivityResult() method as follows

Uri selectedImageUri=intent.getData();
String actualPath=getRealPathFromURI(selectedImageUri);
File file=newFile(actualPath);
Bitmap bitmap=decodeFile(file); //this is new bitmap which you can use for your purpose public String getRealPathFromURI(Uri contentUri) {
        String[] proj = { MediaStore.Images.Media.DATA };
        Cursorcursor= managedQuery(contentUri, proj, null, null, null);
        intcolumn_index= cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }


private Bitmap decodeFile(File f){
        try {
            //Decode image size
            BitmapFactory.Optionso=newBitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(newFileInputStream(f),null,o);

            //The new size we want to scale tofinalint REQUIRED_SIZE=70;

            //Find the correct scale value. It should be the power of 2.int width_tmp=o.outWidth, height_tmp=o.outHeight;
            int scale=1;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale*=2;
            }

            //Decode with inSampleSize
            BitmapFactory.Optionso2=newBitmapFactory.Options();
            o2.inSampleSize=scale;
            return BitmapFactory.decodeStream(newFileInputStream(f), null, o2);
        } catch (FileNotFoundException e) {}
        returnnull;
    }

Hope this helps.This is the very familiar problem when u deal with high quality images taken from phone.check this out too

Solution 2:

Here is my BitmpaHelper class that if OutOfMemoryError proof :-)

import java.io.File;
import java.io.FileInputStream;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

publicclassBitmapHelper
{

    //decodes image and scales it to reduce memory consumptionpublicstatic Bitmap decodeFile(File bitmapFile, int requiredWidth, int requiredHeight, boolean quickAndDirty)
    {
        try
        {
            //Decode image size
            BitmapFactory.OptionsbitmapSizeOptions=newBitmapFactory.Options();
            bitmapSizeOptions.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(newFileInputStream(bitmapFile), null, bitmapSizeOptions);

            // load image using inSampleSize adapted to required image size
            BitmapFactory.OptionsbitmapDecodeOptions=newBitmapFactory.Options();
            bitmapDecodeOptions.inTempStorage = newbyte[16 * 1024];
            bitmapDecodeOptions.inSampleSize = computeInSampleSize(bitmapSizeOptions, requiredWidth, requiredHeight, false);
            bitmapDecodeOptions.inPurgeable = true;
            bitmapDecodeOptions.inDither = !quickAndDirty;
            bitmapDecodeOptions.inPreferredConfig = quickAndDirty ? Bitmap.Config.RGB_565 : Bitmap.Config.ARGB_8888;

            BitmapdecodedBitmap= BitmapFactory.decodeStream(newFileInputStream(bitmapFile), null, bitmapDecodeOptions);

            // scale bitmap to mathc required size (and keep aspect ratio)floatsrcWidth= (float) bitmapDecodeOptions.outWidth;
            floatsrcHeight= (float) bitmapDecodeOptions.outHeight;

            floatdstWidth= (float) requiredWidth;
            floatdstHeight= (float) requiredHeight;

            floatsrcAspectRatio= srcWidth / srcHeight;
            floatdstAspectRatio= dstWidth / dstHeight;

            // recycleDecodedBitmap is used to know if we must recycle intermediary 'decodedBitmap'// (DO NOT recycle it right away: wait for end of bitmap manipulation process to avoid// java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@416ee7d8// I do not excatly understand why, but this way it's OKbooleanrecycleDecodedBitmap=false;

            BitmapscaledBitmap= decodedBitmap;
            if (srcAspectRatio < dstAspectRatio)
            {
                scaledBitmap = getScaledBitmap(decodedBitmap, (int) dstWidth, (int) (srcHeight * (dstWidth / srcWidth)));
                // will recycle recycleDecodedBitmap
                recycleDecodedBitmap = true;
            }
            elseif (srcAspectRatio > dstAspectRatio)
            {
                scaledBitmap = getScaledBitmap(decodedBitmap, (int) (srcWidth * (dstHeight / srcHeight)), (int) dstHeight);
                recycleDecodedBitmap = true;
            }

            // crop image to match required image sizeintscaledBitmapWidth= scaledBitmap.getWidth();
            intscaledBitmapHeight= scaledBitmap.getHeight();

            BitmapcroppedBitmap= scaledBitmap;

            if (scaledBitmapWidth > requiredWidth)
            {
                intxOffset= (scaledBitmapWidth - requiredWidth) / 2;
                croppedBitmap = Bitmap.createBitmap(scaledBitmap, xOffset, 0, requiredWidth, requiredHeight);
                scaledBitmap.recycle();
            }
            elseif (scaledBitmapHeight > requiredHeight)
            {
                intyOffset= (scaledBitmapHeight - requiredHeight) / 2;
                croppedBitmap = Bitmap.createBitmap(scaledBitmap, 0, yOffset, requiredWidth, requiredHeight);
                scaledBitmap.recycle();
            }

            if (recycleDecodedBitmap)
            {
                decodedBitmap.recycle();
            }
            decodedBitmap = null;

            scaledBitmap = null;
            return croppedBitmap;
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
        returnnull;
    }

    /**
     * compute powerOf2 or exact scale to be used as {@link BitmapFactory.Options#inSampleSize} value (for subSampling)
     * 
     * @param requiredWidth
     * @param requiredHeight
     * @param powerOf2
     *            weither we want a power of 2 sclae or not
     * @return
     */publicstaticintcomputeInSampleSize(BitmapFactory.Options options, int dstWidth, int dstHeight, boolean powerOf2)
    {
        intinSampleSize=1;

        // Raw height and width of imagefinalintsrcHeight= options.outHeight;
        finalintsrcWidth= options.outWidth;

        if (powerOf2)
        {
            //Find the correct scale value. It should be the power of 2.inttmpWidth= srcWidth, tmpHeight = srcHeight;
            while (true)
            {
                if (tmpWidth / 2 < dstWidth || tmpHeight / 2 < dstHeight)
                    break;
                tmpWidth /= 2;
                tmpHeight /= 2;
                inSampleSize *= 2;
            }
        }
        else
        {
            // Calculate ratios of height and width to requested height and widthfinalintheightRatio= Math.round((float) srcHeight / (float) dstHeight);
            finalintwidthRatio= Math.round((float) srcWidth / (float) dstWidth);

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

        return inSampleSize;
    }

    publicstatic Bitmap drawableToBitmap(Drawable drawable)
    {
        if (drawable instanceof BitmapDrawable)
        {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        Bitmapbitmap= Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
        Canvascanvas=newCanvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    }

    publicstatic Bitmap getScaledBitmap(Bitmap bitmap, int newWidth, int newHeight)
    {
        intwidth= bitmap.getWidth();
        intheight= bitmap.getHeight();
        floatscaleWidth= ((float) newWidth) / width;
        floatscaleHeight= ((float) newHeight) / height;

        // CREATE A MATRIX FOR THE MANIPULATIONMatrixmatrix=newMatrix();
        // RESIZE THE BIT MAP
        matrix.postScale(scaleWidth, scaleHeight);

        // RECREATE THE NEW BITMAPBitmapresizedBitmap= Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
        return resizedBitmap;
    }

}

Solution 3:

I have same problem in my android app. When you decode a bitmap from a big sized image and set as imageBitmap to an image view probably your application will slow and after a few try you'll get an "out of memory exception"

You can use Universal Image Loader. https://github.com/nostra13/Android-Universal-Image-Loader

Stringurl="file://" + your_file_path_on_sd_card;
com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage(url, ivPicture, options);

Post a Comment for "Problem With Big Images ( Java.lang.outofmemoryerror: Bitmap Size Exceeds Vm Budget )"