How to load large images in Android and avoiding the out of memory error?

how to display large images in android
android bitmap out of memory
android load image from file
how to load images faster in android
how to improve image quality in android programmatically
bitmap.createbitmap out of memory android
glide load large image
how to check image size in android programmatically

I'm working on an app that uses large images (1390 × 870 : 150kb - 50kb). I'm adding images as I tap a trigger/ImageView.

At a certain point I'm getting an out of memory error:

java.lang.OutOfMemoryError
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:613)
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:378)

To resize the image I'm doing this:

Bitmap productIndex = null;
final String imageLoc = IMAGE_LOCATION;
InputStream imageStream;
try {
     imageStream = new FileInputStream(imageLoc);
     productIndex = decodeSampledBitmapFromResource(getResources(), imageLoc, 400, 400);

     productIV.setImageBitmap(productIndex);
     } catch (FileNotFoundException e1) {
          // TODO Auto-generated catch block
          e1.printStackTrace();
     }
}


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

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

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

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(resId, 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) {

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

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

I got this way of resizing to save space from the Android Docs: Loading Large Bitmaps Efficiently

According to the log this like is the culprit in the decodeSampledBitmapFromResource method :

return BitmapFactory.decodeFile(resId, options);

----- edit ----- Here is how I'm adding each item to the FrameLayout.

for(int ps=0;ps<productSplit.size();ps++){
    //split each product by the equals sign
    List<String> productItem = Arrays.asList(productSplit.get(ps).split("="));

    String tempCarID = productItem.get(0);
    tempCarID = tempCarID.replace(" ", "");
    if(String.valueOf(carID).equals(tempCarID)){

        ImageView productIV = new ImageView(Configurator.this);
        LayoutParams productParams = new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        productIV.setId(Integer.parseInt(partIdsList.get(x)));
        productIV.setLayoutParams(productParams);

        final String imageLoc = productItem.get(2);

        InputStream imageStream;
        try {
            imageStream = new FileInputStream(imageLoc);
            productIndex = decodeSampledBitmapFromResource(getResources(), imageLoc, 400, 400);
            productIV.setImageBitmap(productIndex);
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        productLayers.addView(productIV);

    }
}

You can use another bitmap-config to heavily decrease the size of the images. The default is RGB-config ARGB8888 which means four 8-bit channels are used (red, green, blue, alhpa). Alpha is transparency of the bitmap. This occupy a lot of memory - imagesize X 4. So if the imagesize is 4 megapixel 16 megabytes will immidiately be allocated on the heap - quickly exhausting the memory.

Instead - use RGB_565 which to some extent deteriorate the quality - but to compensate this you can dither the images.

So - to your method decodeSampledBitmapFromResource - add the following snippets:

 options.inPreferredConfig = Config.RGB_565;
 options.inDither = true;

In your code:

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

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

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

 // Decode bitmap with inSampleSize set
 options.inJustDecodeBounds = false;
 options.inPreferredConfig = Config.RGB_565;
 options.inDither = true;
 return BitmapFactory.decodeFile(resId, options);
 }

References:

http://developer.android.com/reference/android/graphics/Bitmap.Config.html#ARGB_8888

Loading Large Bitmaps Efficiently, Setting the inJustDecodeBounds property to true while decoding avoids memory allocation, returning null for the bitmap object but setting� Hello Great Blog. When I your app, I note that once I dismiss the app on my phone, then disconnect from the internet and re-open your app, the data

High resolution devices such as S4 usually run out of memory if you do not have your image in the proper folder which is drawable-xxhdpi. You can also put your image into drawable-nodpi. The reason it would run out of memorey if your image just in drawable that the android would scale the image thinking that the image was designed for low resolution.

How we @Naukri avoid Out of Memory (OOM) in Android Applications, There are multiple reasons for an Out of memory error. Some of those are: Loading Large Bitmap, android devices are normally run with limited heap This way we actually got the image of size we require and avoided OOM. Load a Scaled Down Version into Memory. Now that the image dimensions are known, they can be used to decide if the full image should be loaded into memory or if a subsampled version should be loaded instead. Here are some factors to consider: Estimated memory usage of loading the full image in memory.

You can use this beautiful library https://github.com/davemorrissey/subsampling-scale-image-view

Scaling bitmaps before loading to avoid outofmemory error in android, I have seen many devs going mad with the out of memory erorr when they load large sized Duration: 6:31 Posted: Oct 4, 2014 Use Glide which will help you cache images and load the from memory. Glide .with(/*context*/) .load(/*urlToImage*/) .thumbnail(0.5f/*scale*/) //you can even downscale the image .into(imageView); Secondly with Glide you can pause and resume request by observing scrolling behaviour by using the OnScrollChangedListener

Here is how I'm adding each item to the FrameLayout that's the problem, the code keep adding and adding more images, and doesn't matter how well you resize or how much memory the device have, at certain point it WILL run out of memory. That's because every image you add it's keeping in memory.

For this type of situation what the apps do is to use a ViewGroup that can recycle views. I don't know your layout, but usually is a ListView, GridView or a ViewPager, by recycling views you re-use the layout and can dispose re-load images as necessary.

For the specific purpose of loading and resizing images I strongly advise use Picasso library as it is VERY well written, simple to use and stable.

Loading Large Bitmaps Efficiently in Android, Loading large bitmaps into memory is always a pain. We all see OOM(Out Of Memory) errors in our crash reports because of large images. How to load large images in Android and avoiding the out of memory error? (4) Here is how I'm adding each item to the FrameLayout that's the problem, the code keep adding and adding more images, and doesn't matter how well you resize or how much memory the device have, at certain point it WILL run out of memory.

You are still going to need to manage the bitmap memory as I wouldn't try to allocate a total space more than 3x the size of the screen (if you think about it makes sense for scrolling behavior). If you are overlaying one image on top of another, at some point, you're hitting an Out Of Memory error. You may need to look at capturing the prior screen image as a single background image to make sure you still fit within the available memory. Or when a new image overlaps an existing image only load and render the visible portion. If performance becomes an issue, then you may need to consider OpenGL Textures but the memory allocation problem is still the same.

Do go through all of the Displaying Bitmaps Training as it should give you some additional ideas of how to handle display.

Android out of memory: how to load large bitmap from url efficiently, In this tutorial you'll learn how to avoid the android out of memory error by loading large bitmap images from url in an efficient way and display� If you are using a large bitmap as background or something in your application than don’t pull the full image in to the main memory. You can use the insample size property of bitmap to bring the size your screen needs.

Android Out of Memory Error: Causes, Solution and Best practices , Android Out of Memory Error: Causes, Solution and Best practices You are dealing with large bitmaps and loading all of them at run time. a reference to it thus preventing the GC from collecting it), you leak a lot of memory. Out of memory exceptions are common on both Android and iOS if you’re dealing with large files. Recently, when building a Google VR 360 video player, we went over the 1GB of RAM available on older iOS devices pretty quickly.

Displaying Images with the Picasso Library, We can then load a remote image into any ImageView with: Open up your static placeholder or error images in your drawable folders and that you are loading one or more large images that have not been properly resized. Applying these tips to all of your Picasso image loads should resolve any out of memory issues. Try to improve your efficiency by manually calling recycle() on bitmaps you no longer need. While the GC collects some data of Bitmaps which have all their references freed, the actual memory of the image is stored in native memory, and so a call to bitmap.recycle() is required to release this memory when you need it to be released. Hope this helps.

Load Large Bitmaps in Android, Sometimes loading large images leads to “Out of Memory” errors in our crash reports. This will lead to “Out of memory” error when required memory the images will avoid memory allocation and image will not load into�

Comments
  • Once you've loaded a sampled bitmap, do you ever remove it from your View/Adapter when it is no longer visible?
  • it's always visible. I'm running a loop to add items to a FramedLayout. I'll updated my question to show this.
  • I've updated the question. If I recycle the productIndex Bitmap because it destroys the image and not in my FrameLayout anymore.
  • But visually what does this look like, are you overlapping bitmaps (which could be wasteful)? How many bitmaps are you loading up?
  • Yes, I'm having to overlay the bitmaps. This layers images to create a solid image that the user will them send to themselves or others. The user will be able to add as many as needed...
  • what benefit does setting inSampleSize have?
  • BitmapFactory.Options.inDither is deprecated in Android N, you know some alternative to this?
  • @EmersonDallagnol ... I wish I could answer that. I am a bit surprised the flag is deprecated. I'll look into this more in due course of time
  • the images being used are downloaded via an API and stored in the device sd storage
  • It is still possible that they are getting adjusted for high res, maybe you can dig in that direction, I'll research as well and let you know what I find out
  • as far as the image themselves: they are 72 dpi and compressed via photoshop using "export for web and devices". The iOS and Android app both use the same API and Images. The reason images are so big is to account for Retina.
  • Is this worth looking into: Caching Bitmaps