Rectangle 27 13

inSampleSize is a good hint. But a fixed value often doesn't work fine, since large bitmaps from files usually are user files, which can vary from tiny thumbnails to 12MP images from the digicam.

Here's a quick and dirty loading routine. I know there's room for improvement, like a nicer coded loop, using powers of 2 for faster decoding, and so on. But it's a working start...

public static Bitmap loadResizedBitmap( String filename, int width, int height, boolean exact ) {
    Bitmap bitmap = null;
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile( filename, options );
    if ( options.outHeight > 0 && options.outWidth > 0 ) {
        options.inJustDecodeBounds = false;
        options.inSampleSize = 2;
        while (    options.outWidth  / options.inSampleSize > width
                && options.outHeight / options.inSampleSize > height ) {
            options.inSampleSize++;
        }
        options.inSampleSize--;

        bitmap = BitmapFactory.decodeFile( filename, options );
        if ( bitmap != null && exact ) {
            bitmap = Bitmap.createScaledBitmap( bitmap, width, height, false );
        }
    }
    return bitmap;
}

Btw, in the newer APIs there are also lots of BitmapFactory.Option's for fitting the image to screen DPIs, but I'm not sure whether they really simplify anything. Using android.util.DisplayMetrics.density or simply a fixed size for less memory consumption seem to work better imho.

exception - OutofMemoryError: bitmap size exceeds VM budget (Android) ...

android exception bitmap dalvik
Rectangle 27 4

I ended up resizing the bitmap using the following code which seems to have resolved the issue.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeFile(mPathName, options);

exception - OutofMemoryError: bitmap size exceeds VM budget (Android) ...

android exception bitmap dalvik
Rectangle 27 234

Load and Use downscaled Bitmap (for very blurry images)

After experimenting a lot I can now safely give you some solid recommendations that will make your life easier in Android when using the Android Framework.

Never use a the full size of a Bitmap. The bigger the image the more needs to be blurred and also the higher the blur radius needs to be and usually, the higher the blur radius the slower the algorithm.

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap blurTemplate = BitmapFactory.decodeResource(getResources(), R.drawable.myImage, options);

This will load the bitmap with inSampleSize 8, so only 1/64 of the original image. Test what inSampleSize suits your needs, but keep it 2^n (2,4,8,...) to avoid degrading quality due to scaling. See Google doc for more

Another really big advantage is that bitmap loading will be really fast. In my early blur testings I figured that the longest time during the whole blur process was the image loading. So to load a 1920x1080 image from disk my Nexus 5 needed 500ms while the blurring only took another 250 ms or so.

Renderscript provides ScriptIntrinsicBlur which is a Gaussian blur filter. It has good visual quality and is just the fastest you realistically get on Android. Google claims to be "typically 2-3x faster than a multithreaded C implementation and often 10x+ faster than a Java implementation". Renderscript is really sophisticated (using fastes processing device (GPU, ISP,etc.), etc.) and there is also the v8 support library for it making it compatible down to 2.2. Well at least in theory, through my own tests and reports from other devs it seems that it is not possible to use renderscript blindly, since the hardware/driver fragmentation seems to cause problems with some devices, even with higher sdk lvl (e.g. I had troubles with the 4.1 Nexus S) so be careful and test on a lot devices. Here's a simple example that will get you starting

//define this only once if blurring multiple times
RenderScript rs = RenderScript.create(context);

(...)
//this will blur the bitmapOriginal with a radius of 8 and save it in bitmapOriginal
final Allocation input = Allocation.createFromBitmap(rs, bitmapOriginal); //use this constructor for best performance, because it uses USAGE_SHARED mode which reuses memory
final Allocation output = Allocation.createTyped(rs, input.getType());
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setRadius(8f);
script.setInput(input);
script.forEach(output);
output.copyTo(bitmapOriginal);
android.support.v8.renderscript
android {
    ...
    defaultConfig {
        ...
        renderscriptTargetApi 19
        renderscriptSupportModeEnabled true
    }
}

Simple Benchmark on a Nexus 5 - comparing RenderScript with different other java and renderscript implementations:

The average runtime per blur on different pic sizes

Megapixels per sec that can be blurred

Each value is the avg of 250 rounds. RS_GAUSS_FAST is ScriptIntrinsicBlur (and nearly always the fastest), others that start with RS_ are mostly convolve implementations with simple kernels. The details of the algorithms can be found here. This is not purely blurring, but a good portion is garbage collection that is measured. This can be seen in this here (ScriptIntrinsicBlur on 100x100 image with about 500 rounds)

You can check yourself, the benchmark app is in the playstore: BlurBenchmark

If you need multiple blurs for a live blur or similar and your memory allows it do not load the bitmap from drawables multiple times, but keep it "cached" in a member variable. In this case always try to use the same variables, to keep garbage collecting to a minimum.

Also check out the new "inBitmap" option when loading from a file or drawable which will reuse the bitmap memory and saves garbage collection time.

The simple and naive method is just to use 2 imageviews, one blurred and alpha fade them. But if you want a more sophisticated look that smoothly fades from sharp to blur, then check out Roman Nurik's post about how to do it like in his Muzei app.

Basically he explains that he pre-blurs some frames with different blur extends and uses them as keyframes in an animation that looks really smooth

First of all, thanks for your hard work! But I got a question: "because it uses USAGE_SHARED mode which reuses memory". Where did you find the constant USAGE_SHARED? I couldn't find it anywhere.

Renderscript fast Gaussian blur fails with C memory allocation errors on low end devices. Tested on ZTE Z992 (Android 4.1.1) and Kyocera Rise (Android 4.0.4) using the provided Play Store app. Also had a failure report on Samsung Galaxy S3 mini. Since errors occur in the C layer, they cannot be trapped as exceptions in Java, meaning an app crash is unavoidable. Looks like RenderScript may not ready for production use.

for newer gradle versions, use renderscriptSupportModeEnabled true or it will not build! I searched for ever!

java - Fast Bitmap Blur For Android SDK - Stack Overflow

java android image-processing renderscript
Rectangle 27 233

Load and Use downscaled Bitmap (for very blurry images)

After experimenting a lot I can now safely give you some solid recommendations that will make your life easier in Android when using the Android Framework.

Never use a the full size of a Bitmap. The bigger the image the more needs to be blurred and also the higher the blur radius needs to be and usually, the higher the blur radius the slower the algorithm.

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap blurTemplate = BitmapFactory.decodeResource(getResources(), R.drawable.myImage, options);

This will load the bitmap with inSampleSize 8, so only 1/64 of the original image. Test what inSampleSize suits your needs, but keep it 2^n (2,4,8,...) to avoid degrading quality due to scaling. See Google doc for more

Another really big advantage is that bitmap loading will be really fast. In my early blur testings I figured that the longest time during the whole blur process was the image loading. So to load a 1920x1080 image from disk my Nexus 5 needed 500ms while the blurring only took another 250 ms or so.

Renderscript provides ScriptIntrinsicBlur which is a Gaussian blur filter. It has good visual quality and is just the fastest you realistically get on Android. Google claims to be "typically 2-3x faster than a multithreaded C implementation and often 10x+ faster than a Java implementation". Renderscript is really sophisticated (using fastes processing device (GPU, ISP,etc.), etc.) and there is also the v8 support library for it making it compatible down to 2.2. Well at least in theory, through my own tests and reports from other devs it seems that it is not possible to use renderscript blindly, since the hardware/driver fragmentation seems to cause problems with some devices, even with higher sdk lvl (e.g. I had troubles with the 4.1 Nexus S) so be careful and test on a lot devices. Here's a simple example that will get you starting

//define this only once if blurring multiple times
RenderScript rs = RenderScript.create(context);

(...)
//this will blur the bitmapOriginal with a radius of 8 and save it in bitmapOriginal
final Allocation input = Allocation.createFromBitmap(rs, bitmapOriginal); //use this constructor for best performance, because it uses USAGE_SHARED mode which reuses memory
final Allocation output = Allocation.createTyped(rs, input.getType());
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setRadius(8f);
script.setInput(input);
script.forEach(output);
output.copyTo(bitmapOriginal);
android.support.v8.renderscript
android {
    ...
    defaultConfig {
        ...
        renderscriptTargetApi 19
        renderscriptSupportModeEnabled true
    }
}

Simple Benchmark on a Nexus 5 - comparing RenderScript with different other java and renderscript implementations:

The average runtime per blur on different pic sizes

Megapixels per sec that can be blurred

Each value is the avg of 250 rounds. RS_GAUSS_FAST is ScriptIntrinsicBlur (and nearly always the fastest), others that start with RS_ are mostly convolve implementations with simple kernels. The details of the algorithms can be found here. This is not purely blurring, but a good portion is garbage collection that is measured. This can be seen in this here (ScriptIntrinsicBlur on 100x100 image with about 500 rounds)

You can check yourself, the benchmark app is in the playstore: BlurBenchmark

If you need multiple blurs for a live blur or similar and your memory allows it do not load the bitmap from drawables multiple times, but keep it "cached" in a member variable. In this case always try to use the same variables, to keep garbage collecting to a minimum.

Also check out the new "inBitmap" option when loading from a file or drawable which will reuse the bitmap memory and saves garbage collection time.

The simple and naive method is just to use 2 imageviews, one blurred and alpha fade them. But if you want a more sophisticated look that smoothly fades from sharp to blur, then check out Roman Nurik's post about how to do it like in his Muzei app.

Basically he explains that he pre-blurs some frames with different blur extends and uses them as keyframes in an animation that looks really smooth

First of all, thanks for your hard work! But I got a question: "because it uses USAGE_SHARED mode which reuses memory". Where did you find the constant USAGE_SHARED? I couldn't find it anywhere.

Renderscript fast Gaussian blur fails with C memory allocation errors on low end devices. Tested on ZTE Z992 (Android 4.1.1) and Kyocera Rise (Android 4.0.4) using the provided Play Store app. Also had a failure report on Samsung Galaxy S3 mini. Since errors occur in the C layer, they cannot be trapped as exceptions in Java, meaning an app crash is unavoidable. Looks like RenderScript may not ready for production use.

for newer gradle versions, use renderscriptSupportModeEnabled true or it will not build! I searched for ever!

java - Fast Bitmap Blur For Android SDK - Stack Overflow

java android image-processing renderscript
Rectangle 27 233

Load and Use downscaled Bitmap (for very blurry images)

After experimenting a lot I can now safely give you some solid recommendations that will make your life easier in Android when using the Android Framework.

Never use a the full size of a Bitmap. The bigger the image the more needs to be blurred and also the higher the blur radius needs to be and usually, the higher the blur radius the slower the algorithm.

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap blurTemplate = BitmapFactory.decodeResource(getResources(), R.drawable.myImage, options);

This will load the bitmap with inSampleSize 8, so only 1/64 of the original image. Test what inSampleSize suits your needs, but keep it 2^n (2,4,8,...) to avoid degrading quality due to scaling. See Google doc for more

Another really big advantage is that bitmap loading will be really fast. In my early blur testings I figured that the longest time during the whole blur process was the image loading. So to load a 1920x1080 image from disk my Nexus 5 needed 500ms while the blurring only took another 250 ms or so.

Renderscript provides ScriptIntrinsicBlur which is a Gaussian blur filter. It has good visual quality and is just the fastest you realistically get on Android. Google claims to be "typically 2-3x faster than a multithreaded C implementation and often 10x+ faster than a Java implementation". Renderscript is really sophisticated (using fastes processing device (GPU, ISP,etc.), etc.) and there is also the v8 support library for it making it compatible down to 2.2. Well at least in theory, through my own tests and reports from other devs it seems that it is not possible to use renderscript blindly, since the hardware/driver fragmentation seems to cause problems with some devices, even with higher sdk lvl (e.g. I had troubles with the 4.1 Nexus S) so be careful and test on a lot devices. Here's a simple example that will get you starting

//define this only once if blurring multiple times
RenderScript rs = RenderScript.create(context);

(...)
//this will blur the bitmapOriginal with a radius of 8 and save it in bitmapOriginal
final Allocation input = Allocation.createFromBitmap(rs, bitmapOriginal); //use this constructor for best performance, because it uses USAGE_SHARED mode which reuses memory
final Allocation output = Allocation.createTyped(rs, input.getType());
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setRadius(8f);
script.setInput(input);
script.forEach(output);
output.copyTo(bitmapOriginal);
android.support.v8.renderscript
android {
    ...
    defaultConfig {
        ...
        renderscriptTargetApi 19
        renderscriptSupportModeEnabled true
    }
}

Simple Benchmark on a Nexus 5 - comparing RenderScript with different other java and renderscript implementations:

The average runtime per blur on different pic sizes

Megapixels per sec that can be blurred

Each value is the avg of 250 rounds. RS_GAUSS_FAST is ScriptIntrinsicBlur (and nearly always the fastest), others that start with RS_ are mostly convolve implementations with simple kernels. The details of the algorithms can be found here. This is not purely blurring, but a good portion is garbage collection that is measured. This can be seen in this here (ScriptIntrinsicBlur on 100x100 image with about 500 rounds)

You can check yourself, the benchmark app is in the playstore: BlurBenchmark

If you need multiple blurs for a live blur or similar and your memory allows it do not load the bitmap from drawables multiple times, but keep it "cached" in a member variable. In this case always try to use the same variables, to keep garbage collecting to a minimum.

Also check out the new "inBitmap" option when loading from a file or drawable which will reuse the bitmap memory and saves garbage collection time.

The simple and naive method is just to use 2 imageviews, one blurred and alpha fade them. But if you want a more sophisticated look that smoothly fades from sharp to blur, then check out Roman Nurik's post about how to do it like in his Muzei app.

Basically he explains that he pre-blurs some frames with different blur extends and uses them as keyframes in an animation that looks really smooth

First of all, thanks for your hard work! But I got a question: "because it uses USAGE_SHARED mode which reuses memory". Where did you find the constant USAGE_SHARED? I couldn't find it anywhere.

Renderscript fast Gaussian blur fails with C memory allocation errors on low end devices. Tested on ZTE Z992 (Android 4.1.1) and Kyocera Rise (Android 4.0.4) using the provided Play Store app. Also had a failure report on Samsung Galaxy S3 mini. Since errors occur in the C layer, they cannot be trapped as exceptions in Java, meaning an app crash is unavoidable. Looks like RenderScript may not ready for production use.

for newer gradle versions, use renderscriptSupportModeEnabled true or it will not build! I searched for ever!

java - Fast Bitmap Blur For Android SDK - Stack Overflow

java android image-processing renderscript
Rectangle 27 96

One of the most common errors that I found developing Android Apps is the java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget error. I found this error frequently on activities using lots of bitmaps after changing orientation: the Activity is destroyed, created again and the layouts are inflated from the XML consuming the VM memory available for bitmaps.

Bitmaps on the previous activity layout are not properly de-allocated by the garbage collector because they have crossed references to their activity. After many experiments I found a quite good solution for this problem.

First, set the id attribute on the parent view of your XML layout:

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:id="@+id/RootView"
     >
     ...

Then, on the onDestroy() method of your Activity, call the unbindDrawables() method passing a reference to the parent View and then do a System.gc().

@Override
    protected void onDestroy() {
    super.onDestroy();

    unbindDrawables(findViewById(R.id.RootView));
    System.gc();
    }

    private void unbindDrawables(View view) {
        if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup) {
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
            }
        ((ViewGroup) view).removeAllViews();
        }
    }

This unbindDrawables() method explores the view tree recursively and:

  • Removes callbacks on all the background drawables

Except... java.lang.UnsupportedOperationException: removeAllViews() is not supported in AdapterView

Thanks this helps reduce my heap size significantly since I have a lot of drawables ... @GJTorikian for that just try catch at removeAllViews() most ViewGroup subclasses work just fine.

Or just change the condition: if (view instanceof ViewGroup && !(view instanceof AdapterView))

@Adam Varhegyi, you can explicitly call same function for gallery view in onDestroy. Like unbindDrawables(galleryView); hope this works for you...

memory - java.lang.OutOfMemoryError: bitmap size exceeds VM budget - A...

android memory memory-leaks bitmap out-of-memory
Rectangle 27 96

One of the most common errors that I found developing Android Apps is the java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget error. I found this error frequently on activities using lots of bitmaps after changing orientation: the Activity is destroyed, created again and the layouts are inflated from the XML consuming the VM memory available for bitmaps.

Bitmaps on the previous activity layout are not properly de-allocated by the garbage collector because they have crossed references to their activity. After many experiments I found a quite good solution for this problem.

First, set the id attribute on the parent view of your XML layout:

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:id="@+id/RootView"
     >
     ...

Then, on the onDestroy() method of your Activity, call the unbindDrawables() method passing a reference to the parent View and then do a System.gc().

@Override
    protected void onDestroy() {
    super.onDestroy();

    unbindDrawables(findViewById(R.id.RootView));
    System.gc();
    }

    private void unbindDrawables(View view) {
        if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup) {
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
            }
        ((ViewGroup) view).removeAllViews();
        }
    }

This unbindDrawables() method explores the view tree recursively and:

  • Removes callbacks on all the background drawables

Except... java.lang.UnsupportedOperationException: removeAllViews() is not supported in AdapterView

Thanks this helps reduce my heap size significantly since I have a lot of drawables ... @GJTorikian for that just try catch at removeAllViews() most ViewGroup subclasses work just fine.

Or just change the condition: if (view instanceof ViewGroup && !(view instanceof AdapterView))

@Adam Varhegyi, you can explicitly call same function for gallery view in onDestroy. Like unbindDrawables(galleryView); hope this works for you...

memory - java.lang.OutOfMemoryError: bitmap size exceeds VM budget - A...

android memory memory-leaks bitmap out-of-memory
Rectangle 27 5

As greenapps suggested, it would be better to avoid using Bitmap and BitmapFactory in order to TRANSMIT the file:

FileInputStream fis = new FileInputStream(imageFile);
byte[] byteArray = inputStreamToByteArray(fis);
String base64ImageSend = Base64.encodeToString(byteArray, Base64.NO_WRAP);
/**
 * Convert an InputStream object into a byte array
 * @param inputStream The InputStream to convert
 * @return The byte[] representing the converted InputStream or null if the inputStream is null
 */
public static byte[] inputStreamToByteArray(InputStream inputStream) throws IOException {
    if(inputStream==null) {
        return null;
    }
    ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
    int bufferSize = 1024;
    byte[] buffer = new byte[bufferSize];

    int len = 0;
    while ((len = inputStream.read(buffer)) != -1) {
        byteBuffer.write(buffer, 0, len);
    }
    return byteBuffer.toByteArray();
}

Actually the outOfMemory problem, as stated by Kai, is due to the fact that you are decoding a full resolution and high quality image. The better way to avoid this is to downsampling your image:

/**
 * Decode a file, representing an image, into a bitmap, trying to scale the original image if required
 * @param context The application context
 * @param file The image file
 * @param requestedWidth The requested width
 * @param requestedHeight The requested height
 * @return The decoded bitmap or null if it is not possible to decode the file parameter
 */
public static Bitmap decodeImageFileIntoMutableBitmap(Context context, File file, int requestedWidth, int requestedHeight) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true; // just compute size, don't create bitmap
    BitmapFactory.decodeFile(file.getAbsolutePath(), options);
    float sampleSize = computeImageScaleCoefficient(options, requestedWidth, requestedHeight);
    if (sampleSize == -1) {
        return null;
    }
    else if (sampleSize <= 1) {
        options.inSampleSize = 1;
    }
    else {
        options.inSampleSize = (int) sampleSize;
    }
    options.inJustDecodeBounds = false; // compute size and create bitmap
    /*it is possible to reduce the memory when decoding through skipping ARGB_8888 and using RGB_565 instead and inDither to true to preserve image quality.*/
    //options.inPreferredConfig = Bitmap.Config.RGB_565;
    //options.inDither = true;
    Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
    if (bitmap == null) {
        return null;
    }
    return bitmap;
}

/**
 * Find the sample coefficient <code><b>s<sub>k</sub></b>=2<sup>k</sup></code>, with <code>k &isin &#8469;</code>, such that
 * <code>min<sub>k</sub>(requestedWidth-options.outWidth&times;<b>s<sub>k</sub></b>)&gt;0</code>
 * <code>&&</code>
 * <code>min<sub>k</sub>(requestedHeight-options.outHeight&times;<b>s<sub>k</sub></b>)&gt;0</code>
 * @param options The BitmapFactory.Options instance of the original image user wants to scale
 * @param requestedWidth The requested width
 * @param requestedHeight The requested height
 * @return -1 if if there is an error trying to decode the image
 * or the sample coefficient <code><b>s<sub>k</sub></b></code>,
 * &gt;1 if the image needs to be down-sampled,
 * &lt;1 if the image needs to be up-sampled
 */
public static float computeImageScaleCoefficient(BitmapFactory.Options options, int requestedWidth, int requestedHeight) {
    float sampleCoefficient = 1;
    int imageWidth = options.outWidth;
    int imageHeight = options.outHeight;
    if (imageWidth == -1 || imageHeight == -1) {
        return -1;
    }
    double outWidth = imageWidth;
    double outHeight = imageHeight;
    if ((outWidth > requestedWidth) || (outHeight > requestedHeight)) {
        while ((outWidth > requestedWidth) || (outHeight > requestedHeight)) {
            outWidth = Math.floor(outWidth/2.0);
            outHeight = Math.floor(outHeight/2.0);
            sampleCoefficient *= 2.0;
        }
    }
    else {
        while ((outWidth < requestedWidth) && (outHeight < requestedHeight)) {
            outWidth *= 2;
            outHeight *= 2;
            if ((outWidth <= requestedWidth) && (outHeight <= requestedHeight)) {
                sampleCoefficient /= 2.0;
            }
        }
    }
    return sampleCoefficient;
}

java - OutOfMemoryError while decoding and encoding Base64 String into...

java android image bitmap base64
Rectangle 27 91

Verifying App Behavior on the Android Runtime (ART)

You can't increase the heap size dynamically but you can request to use more by using.

in the manifest.xml,you can add in your manifest these lines it is working for some situations.

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

Whether your application's processes should be created with a large Dalvik heap. This applies to all processes created for the application. It only applies to the first application loaded into a process; if you're using a shared user ID to allow multiple applications to use a process, they all must use this option consistently or they will have unpredictable results. Most apps should not need this and should instead focus on reducing their overall memory usage for improved performance. Enabling this also does not guarantee a fixed increase in available memory, because some devices are constrained by their total available memory.

To query the available memory size at runtime, use the methods getMemoryClass() or getLargeMemoryClass().

If still facing problem then this should also work

BitmapFactory.Options options = new BitmapFactory.Options();
 options.inSampleSize = 8;
 mBitmapInsurance = BitmapFactory.decodeFile(mCurrentPhotoPath,options);

This is the optimal use of BitmapFactory.Options.inSampleSize with regards to speed of displaying the image. The documentation mentions using values that are a power of 2, so I am working with 2, 4, 8, 16 etc.

For example, its not worth loading a 1024x768 pixel image into memory if it will eventually be displayed in a 128x128 pixel thumbnail in an ImageView.

To tell the decoder to subsample the image, loading a smaller version into memory, set inSampleSize to true in your BitmapFactory.Options object. For example, an image with resolution 2100 x 1500 pixels that is decoded with an inSampleSize of 4 produces a bitmap of approximately 512x384. Loading this into memory uses 0.75MB rather than 12MB for the full image (assuming a bitmap configuration of ARGB_8888). Heres a method to calculate a sample size value that is a power of two based on a target width and height:

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;
}

Note: A power of two value is calculated because the decoder uses a final value by rounding down to the nearest power of two, as per the inSampleSize documentation.

To use this method, first decode with inJustDecodeBounds set to true, pass the options through and then decode again using the new inSampleSize value and inJustDecodeBounds set to false:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

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

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

This method makes it easy to load a bitmap of arbitrarily large size into an ImageView that displays a 100x100 pixel thumbnail, as shown in the following example code:

mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

You can follow a similar process to decode bitmaps from other sources, by substituting the appropriate BitmapFactory.decode* method as needed.

private Bitmap getBitmap(String path) {

Uri uri = getImageUri(path);
InputStream in = null;
try {
    final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
    in = mContentResolver.openInputStream(uri);

    // Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(in, null, o);
    in.close();

    int scale = 1;
    while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) > 
          IMAGE_MAX_SIZE) {
       scale++;
    }
    Log.d(TAG, "scale = " + scale + ", orig-width: " + o.outWidth + ", 
       orig-height: " + o.outHeight);

    Bitmap bitmap = null;
    in = mContentResolver.openInputStream(uri);
    if (scale > 1) {
        scale--;
        // scale to max possible inSampleSize that still yields an image
        // larger than target
        o = new BitmapFactory.Options();
        o.inSampleSize = scale;
        bitmap = BitmapFactory.decodeStream(in, null, o);

        // resize to desired dimensions
        int height = bitmap.getHeight();
        int width = bitmap.getWidth();
        Log.d(TAG, "1th scale operation dimenions - width: " + width + ",
           height: " + height);

        double y = Math.sqrt(IMAGE_MAX_SIZE
                / (((double) width) / height));
        double x = (y / height) * width;

        Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int) x, 
           (int) y, true);
        bitmap.recycle();
        bitmap = scaledBitmap;

        System.gc();
    } else {
        bitmap = BitmapFactory.decodeStream(in);
    }
    in.close();

    Log.d(TAG, "bitmap size - width: " +bitmap.getWidth() + ", height: " + 
       bitmap.getHeight());
    return bitmap;
} catch (IOException e) {
    Log.e(TAG, e.getMessage(),e);
    return null;
}
android:largeHeap="true"

However, the ability to request a large heap is intended only for a small set of apps that can justify the need to consume more RAM (such as a large photo editing app). Never request a large heap simply because you've run out of memory and you need a quick fixyou should use it only when you know exactly where all your memory is being allocated and why it must be retained. Yet, even when you're confident your app can justify the large heap, you should avoid requesting it to whatever extent possible. Using the extra memory will increasingly be to the detriment of the overall user experience because garbage collection will take longer and system performance may be slower when task switching or performing other common operations.

After working excrutiatingly with out of memory errors i would say adding this to the manifest to avoid the oom issue is not a sin

The Android runtime (ART) is the default runtime for devices running Android 5.0 (API level 21) and higher. This runtime offers a number of features that improve performance and smoothness of the Android platform and apps. You can find more information about ART's new features in Introducing ART.

Under Dalvik, apps frequently find it useful to explicitly call System.gc() to prompt garbage collection (GC). This should be far less necessary with ART, particularly if you're invoking garbage collection to prevent GC_FOR_ALLOC-type occurrences or to reduce fragmentation. You can verify which runtime is in use by calling System.getProperty("java.vm.version"). If ART is in use, the property's value is "2.0.0" or higher.

Furthermore, a compacting garbage collector is under development in the Android Open-Source Project (AOSP) to improve memory management. Because of this, you should avoid using techniques that are incompatible with compacting GC (such as saving pointers to object instance data). This is particularly important for apps that make use of the Java Native Interface (JNI). For more information, see Preventing JNI Issues.

ART's JNI is somewhat stricter than Dalvik's. It is an especially good idea to use CheckJNI mode to catch common problems. If your app makes use of C/C++ code, you should review the following article:

Also, you can use native memory (NDK & JNI), so you actually bypass the heap size limitation.

Here are some posts made about it:

and here's a library made for it:

Your android:largeHeap="true" tricks helps me a lot. Thanks a lot sir

Gattsu
"For example, its not worth loading a 1024x768 pixel image into memory if it will eventually be displayed in a 128x96 pixel thumbnail in an ImageView."

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

bitmap - How to solve java.lang.OutOfMemoryError trouble in Android - ...

android bitmap out-of-memory bitmapfactory setbackground
Rectangle 27 2

You might want to consider using the inSampleSize property of the BitmapFactory.Options class. This property will rescale your image by a power of 2 (which you decide) when the bitmap object is created, which will save memory. If the resolution of the picture is greater than the resolution of the screen, this should work perfectly well for you, without degrading the quality of the picture.

To use this for an image you are downloading from a server, you can use it as follows:

URL url = new URL(photoUrl);
URLConnection ucon = url.openConnection();

Options options = new Options();
options.inSampleSize = 2;

Bitmap bitmap = BitmapFactory.decodeStream(ucon.getInputStream(),null, options);

An alternative is to also wrap each bitmap object in your HashMap with a SoftReference object so that the VM will reclaim the memory used by bitmaps, rather than crashing with an OOM error. The downside is that you would have to reload the bitmap and personally, I feel that the VM is aggressive when reclaiming memory. It reclaims memory pretty quickly.

Out Of memory error - Bitmap exceeds VM budget in Android while using ...

android bitmap maps out-of-memory
Rectangle 27 81

Instead of using Bitmap, you can also do this through trivial InputStream. Well I am not sure, but I think its a bit efficient

InputStream inputStream = new FileInputStream(fileName);//You can get an inputStream using any IO API
byte[] bytes;
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
    while ((bytesRead = inputStream.read(buffer)) != -1) {
    output.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
bytes = output.toByteArray();
String encodedString = Base64.encodeToString(bytes, Base64.DEFAULT);

Of course this is more efficient; just transforms a file into its base64 representation, and avoids an absolutely meaningless recompression of the image.

+1 for showing a more efficient way of doing it.

is the fileName here the path of the file or the actual file name ??? Please don't forget to tag me :) Thanks.

@user2247689 When you are trying to access a file obviously you have to give the complete path of the file including its name. If the file is present in the same path where your source program is present, then file name is enough.

A question, what does '8192' signifies here, is it file size or what?

android - How to convert a image into Base64 string? - Stack Overflow

android base64
Rectangle 27 44

Using byte instead of int for raw pixel data

public class DirectBitmap : IDisposable
{
    public Bitmap Bitmap { get; private set; }
    public Int32[] Bits { get; private set; }
    public bool Disposed { get; private set; }
    public int Height { get; private set; }
    public int Width { get; private set; }

    protected GCHandle BitsHandle { get; private set; }

    public DirectBitmap(int width, int height)
    {
        Width = width;
        Height = height;
        Bits = new Int32[width * height];
        BitsHandle = GCHandle.Alloc(Bits, GCHandleType.Pinned);
        Bitmap = new Bitmap(width, height, width * 4, PixelFormat.Format32bppPArgb, BitsHandle.AddrOfPinnedObject());
    }

    public void Dispose()
    {
        if (Disposed) return;
        Disposed = true;
        Bitmap.Dispose();
        BitsHandle.Free();
    }
}

There's no need for LockBits or SetPixel. Use the above class for direct access to bitmap data.

With this class, it is possible to set raw bitmap data as 32-bit data. Notice that it is PARGB, which is premultiplied alpha. See Alpha Compositing on Wikipedia for more information on how this works and examples on the MSDN article for BLENDFUNCTION to find out how to calculate the alpha properly.

If premultiplication might overcomplicate things, use PixelFormat.Format32bppArgb instead. A performance hit occurs when it's drawn, because it's internally being converted to PixelFormat.Format32bppPArgb. If the image doesn't have to change prior to being drawn, the work can be done before premultiplication, drawn to a PixelFormat.Format32bppArgb buffer, and further used from there.

Access to standard Bitmap members is exposed via the Bitmap property. Bitmap data is directly accessed using the Bits property.

Change both instances of Int32 to byte, and then change this line:

Bits = new Int32[width * height];
Bits = new byte[width * height * 4];

When bytes are used, the format is Alpha/Red/Green/Blue in that order. Each pixel takes 4 bytes of data, one for each channel.

  • Memory allocation for merely manipulating the data is unnecessary; changes made to the raw data are immediately applied to the bitmap.
IDisposable
Bitmap
  • It does not require an unsafe block.
  • Pinned memory cannot be moved. It's a required side effect in order for this kind of memory access to work. This reduces the efficiency of the garbage collector (MSDN Article). Do it only with bitmaps where performance is required, and be sure to Dispose them when you're done so the memory can be unpinned.

Because the Bitmap property is actually a .NET Bitmap object, it's straightforward to perform operations using the Graphics class.

var dbm = new DirectBitmap(200, 200);
using (var g = Graphics.FromImage(dbm.Bitmap))
{
    g.DrawRectangle(Pens.Black, new Rectangle(50, 50, 100, 100));
}

This is brilliant, thank You. It is the same speed or even a bit faster as with LockBits and pointers without the need to unsafe code. I wonder why this is not provided as preferred approach.

It is probably not provided as a default because it is an unmanaged object (rather, the underlying data is unmanaged) and runs counter to the philosophy of the framework. But this version is certainly more useful for frequent image manipulations.

How do you make an instance of DirectBitmap with the original bitmap? I noticed the byte array is coming from GCHandle.Alloc (which I'm kind of new to).

DirectBitmap needs to be created from the ground up. If you need to create one from an existing Bitmap, you need to create a DirectBitmap with the same dimensions, and use a Graphics object to copy it over.

@SaxxonPike Can you explain how you copy over from Graphics to DirectBitmap? If possible, a use-case sample for DirectBitmap would be great.

drawing - C# - Faster Alternatives to SetPixel and GetPixel for Bitmap...

c# drawing gdi+ getpixel
Rectangle 27 13

Following your code: method decodeBase64 holds String input argument parameter in the stack, byte[] decodedBytereference and return BitmapFactory.decodeStream(new FileInputStream(f), null, o2) at the very end. Holding all these objects in the memory at the same time makes big pressure on it. As a simplest solution you can null references just after corresponding objects were used (string and byte array), so GC will be able to free up them.

java - OutOfMemoryError while decoding and encoding Base64 String into...

java android image bitmap base64
Rectangle 27 3

the problem is, that you create a scaled Bitmap by using the old big one. After that you have two Bitmaps in your Memory and you don't even recycle the old one.

ImageView imageView = (ImageView) findViewById(R.id.some_id);
String pathToImage = "path";

BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathToImage, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;

// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/50, photoH/50);

// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;

Bitmap bitmap = BitmapFactory.decodeFile(pathToFile, bmOptions);
imageView.setImageBitmap(bitmap);

When you want to use a resource Id instead of the file path, use decodeResource and do the last part like this:

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resourceId, bmOptions);
imageView.setImageBitmap(bitmap);

Hope that piece of code helps you out!

Thanks Chris! Just one question, the path, do I need to get it in a string? Or is it possible to get this with int resId = C.getResources().getIdentifier(name, "drawable", "com.test.com"); and to use decodeFile(resId, ...)?

Edited my post - hope that helps you out! If yes, please mark the post as correct answer, it's Christmas ;)

Hey Chris, I sure will do that ;) It works now! I only have a big quality loss.. especially the edges with this method.. I found on SA that adding bmOptions.inScaled = false; bmOptions.inDither = false; bmOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; would solve this, but it doens't ... :s

Thanks, if this [thread] (stackoverflow.com/questions/4231817/) doesn't help, you're Images might just don't look well when you scale them down - try it out in Photoshop...

Sorry but, am I not having my original code again then? It's not much difference.. thanks for the help so far!

android - OutOfMemoryError when loading my gridview with images - Stac...

android memory gridview
Rectangle 27 7

1) NEVER call System.gc() yourself. This has been propagated as a fix here, and it doesn't work. Do not do it. If you noticed in my explanation, before getting an OutOfMemoryError, the JVM already runs a garbage collection so there is no reason to do one again (its slowing your program down). Doing one at the end of your activity is just covering up the problem. It may causes the bitmap to be put on the finalizer queue faster, but there is no reason you couldn't have simply called recycle on each bitmap instead.

2) Always call recycle() on bitmaps you don't need anymore. At the very least, in the onDestroy of your activity go through and recycle all the bitmaps you were using. Also, if you want the bitmap instances to be collected from the dalvik heap faster, it doesn't hurt to clear any references to the bitmap.

3) Calling recycle() and then System.gc() still might not remove the bitmap from the Dalvik heap. DO NOT BE CONCERNED about this. recycle() did its job and freed the native memory, it will just take some time to go through the steps I outlined earlier to actually remove the bitmap from the Dalvik heap. This is NOT a big deal because the large chunk of native memory is already free!

4) Always assume there is a bug in the framework last. Dalvik is doing exactly what its supposed to do. It may not be what you expect or what you want, but its how it works. "

memory - java.lang.OutOfMemoryError: bitmap size exceeds VM budget - A...

android memory memory-leaks bitmap out-of-memory
Rectangle 27 7

1) NEVER call System.gc() yourself. This has been propagated as a fix here, and it doesn't work. Do not do it. If you noticed in my explanation, before getting an OutOfMemoryError, the JVM already runs a garbage collection so there is no reason to do one again (its slowing your program down). Doing one at the end of your activity is just covering up the problem. It may causes the bitmap to be put on the finalizer queue faster, but there is no reason you couldn't have simply called recycle on each bitmap instead.

2) Always call recycle() on bitmaps you don't need anymore. At the very least, in the onDestroy of your activity go through and recycle all the bitmaps you were using. Also, if you want the bitmap instances to be collected from the dalvik heap faster, it doesn't hurt to clear any references to the bitmap.

3) Calling recycle() and then System.gc() still might not remove the bitmap from the Dalvik heap. DO NOT BE CONCERNED about this. recycle() did its job and freed the native memory, it will just take some time to go through the steps I outlined earlier to actually remove the bitmap from the Dalvik heap. This is NOT a big deal because the large chunk of native memory is already free!

4) Always assume there is a bug in the framework last. Dalvik is doing exactly what its supposed to do. It may not be what you expect or what you want, but its how it works. "

memory - java.lang.OutOfMemoryError: bitmap size exceeds VM budget - A...

android memory memory-leaks bitmap out-of-memory
Rectangle 27 3

I too am frustrated by the outofmemory bug. And yes, I too found that this error pops up a lot when scaling images. At first I tried creating image sizes for all densities, but I found this substantially increased the size of my app. So I'm now just using one image for all densities and scaling my images.

My application would throw an outofmemory error whenever the user went from one activity to another. Setting my drawables to null and calling System.gc() didn't work, neither did recycling my bitmapDrawables with getBitMap().recycle(). Android would continue to throw the outofmemory error with the first approach, and it would throw a canvas error message whenever it tried using a recycled bitmap with the second approach.

I took an even third approach. I set all views to null and the background to black. I do this cleanup in my onStop() method. This is the method that gets called as soon as the activity is no longer visible. If you do it in the onPause() method, users will see a black background. Not ideal. As for doing it in the onDestroy() method, there is no guarantee that it will get called.

To prevent a black screen from occurring if the user presses the back button on the device, I reload the activity in the onRestart() method by calling the startActivity(getIntent()) and then finish() methods.

memory - java.lang.OutOfMemoryError: bitmap size exceeds VM budget - A...

android memory memory-leaks bitmap out-of-memory
Rectangle 27 3

I too am frustrated by the outofmemory bug. And yes, I too found that this error pops up a lot when scaling images. At first I tried creating image sizes for all densities, but I found this substantially increased the size of my app. So I'm now just using one image for all densities and scaling my images.

My application would throw an outofmemory error whenever the user went from one activity to another. Setting my drawables to null and calling System.gc() didn't work, neither did recycling my bitmapDrawables with getBitMap().recycle(). Android would continue to throw the outofmemory error with the first approach, and it would throw a canvas error message whenever it tried using a recycled bitmap with the second approach.

I took an even third approach. I set all views to null and the background to black. I do this cleanup in my onStop() method. This is the method that gets called as soon as the activity is no longer visible. If you do it in the onPause() method, users will see a black background. Not ideal. As for doing it in the onDestroy() method, there is no guarantee that it will get called.

To prevent a black screen from occurring if the user presses the back button on the device, I reload the activity in the onRestart() method by calling the startActivity(getIntent()) and then finish() methods.

memory - java.lang.OutOfMemoryError: bitmap size exceeds VM budget - A...

android memory memory-leaks bitmap out-of-memory
Rectangle 27 41

If you are wanting to fill a bitmap with a solid colour you could try using

Bitmap b = /*however you get a bmp*/
b.eraseColor(color)

It clears the bitmap by filling all pixels with a colour.

Might be the effect you want

How to fill bitmap object with color in Android - Stack Overflow

android bitmap
Rectangle 27 33

The memory that backs a Bitmap object is allocated using native code (malloc()), rather than the Java new keyword. This means that the memory is managed directly by the OS, rather than by Dalvik.

The only real difference between the native heap and Dalvik's heap is that Dalvik's heap is garbage collected, and the native one isn't.

For these purposes though, here's not much difference. When your Bitmap object gets garbage collected, it's destructor will recycle the associated memory in the native heap.

Do you know if this bug was ever fixed? I'm currently running into the same problem on the thunder bolt. I'm recycling the bitmaps but they're never clearing any space on the native heap causing oom errors.

Just for clarity, the above answer is true for android version 2.x and below. Starting with Android 3, bitmap instances are counter agains the heap. This can easily be checked: creating a bitmap in android 2.x will leave the Java heap size pretty much intouched, creating it in Adnroid 3.x will add a lot of bytes to the Java heap.

Ah! so you are saying the counting is now much more intuitive? That's great - except for all of us who wrote hacky code to sum the android heap with the native heap ...

Bitmaps in Android - Stack Overflow

android bitmap