High resolution Image - OutOfMemoryError

android, android-imageview, bitmap, image, out-of-memory

Solution

Three hints which should help you:

Use this to load your images, from Loading Large Bitmaps Android documentation:

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

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 larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
}

Make sure you have only one instance of your `Bitmap` in memory. After displaying it, call `recycle()` and set your reference to `null`. You can use Memory Allocation Tracker to see what is allocated. You can also read HPROF files, as suggested in comments.

By default `ARGB_8888` pixel format is used, which means 4 bytes per pixel. Very good article: Bitmap quality, banding and dithering. Your image is JPEG, so it doesn't have transparency, so you are wasting 1 byte on every pixel for alpha channel. It's not very probable, but maybe with acceptable quality you can use even more economical format. Take a look at them. Maybe `RGB_565` for example. It takes 2 bytes for pixel, so your image would be 50% lighter. You can enable dithering to improve the quality of `RGB_565`.

Problem

I am developing an application for the Galaxy S4. One of the requirements of the application is having a SplashScreen containing an Image of 1920x1080 pixels. Its a high quality .jpeg image and the size of the Image is about 2 Megabytes. The problem is that I am getting an OutOfMemoryError as soon as I start the Application. I am quite stunned that this already happens with an image of just 2 megabyte in size? How can I fix this problem and display the image? Changing the dimensions or the size of the image is not an option. SplashScreen.java ``` public class Splashscreen extends Activity { private static final int SPLASH_DURATION = 2000; private boolean isBackPressed = false; @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(LayoutParams.FLAG_FULLSCREEN, LayoutParams.FLAG_FULLSCREEN); super.onCreate(savedInstanceState); setContentView(R.layout.splashscreen); Handler h = new Handler(); h.postDelayed(new Runnable() { @Override public void run() { // check if the backbutton has been pressed within the splash_duration if(!isBackPressed) { Intent i = new Intent(Splashscreen.this, MainActivity.class); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); Splashscreen.this.startActivity(i); overridePendingTransition(R.anim.short_fade_in, R.anim.short_fade_out); } finish(); } }, SPLASH_DURATION); } @Override public void onBackPressed() { isBackPressed = true; super.onBackPressed(); } } ``` And the splashscreen.xml ``` <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ivSplashScreenImage" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" android:src="@drawable/high_res_splashscreen_image"/> ``` ADDITIONAL INFORMATION: Sometimes, (when a lot of device memory is available) the app is able to make it past the splash screen, but then, the memory consumption of the app is just insane. (around 100 megabyte). Even though I close the SplashScreen Activity and finish() it, it seems that there is a reference to the ImageView / the Image kept in memory. How can I reduce the huge memory consumption? When I do not display the splash screen, my app only consumes around 35MB of memory. With the SplashScreen image, its around 100MB.

Original source

Related problems