0

I wanted to create an activity in which the user can set the background. Unfortunately the images are 'too big', when I'm loading about 7 images it throws an exception (Failed to allocate a 74649612 byte allocation with 7804240 free bytes and 7MB until OOM). Is there a way to make the images 'smaller' inside Android Studio, without scaling it down in photoshop?

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    (...)
    ImageView image_1 = (ImageView) findViewById(R.id.image_1);
    ImageView image_2 = (ImageView) findViewById(R.id.image_2);
    ...

    image_1.setImageDrawable(getDrawable(R.drawable.background_1));
    image_2.setImageDrawable(getDrawable(R.drawable.background_2));
    ...

I alredy enabled android:largeHeap="true" in the AndroidManifest.xml.

Thanks for your help.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Thomi
  • 194
  • 1
  • 2
  • 12
  • Possible duplicate of [Android:java.lang.OutOfMemoryError: Failed to allocate a 23970828 byte allocation with 2097152 free bytes and 2MB until OOM](https://stackoverflow.com/questions/32244851/androidjava-lang-outofmemoryerror-failed-to-allocate-a-23970828-byte-allocatio) – Shaishav Jul 19 '17 at 13:07
  • first of all, DO NOT USE largeHeap="true", try to optimize your images with some lossy/lossless compression, convert it to webp, scale down, etc... – mayosk Jul 19 '17 at 13:08
  • https://developer.android.com/topic/performance/graphics/load-bitmap.html everything is explained here in simple steps – AndroidGeek Jul 19 '17 at 13:10
  • Thanks for your help, I saw the it but it didn't really help me. – Thomi Jul 19 '17 at 13:55

3 Answers3

0

I thinks so this can help u.

Handling Bitmaps

Or u can use Glide Library.

Shahbaz Ansari
  • 187
  • 1
  • 10
0

You can solve this problem by decreasing the size of the drawable images, to do that you need to first convert images to bitmap then use the following code to decrease the size of the bitmap

  public static Bitmap makeBitmap(String fn, int minSideLength, int maxNumOfPixels) {
BitmapFactory.Options options;
try {
    options = new BitmapFactory.Options();

    options.inPurgeable = true;
    options.inJustDecodeBounds = true;
    BitmapFactory.BitmapFactory.decodeResource(getResources(), R.drawable.large_icon,options);
    if (options.mCancel || options.outWidth == -1
            || options.outHeight == -1) {
        return null;
    }
    options.inSampleSize = computeSampleSize(
            options, minSideLength, maxNumOfPixels);
    options.inJustDecodeBounds = false;
    //Log.e(LOG_TAG, "sample size=" + options.inSampleSize);

    options.inDither = false;
    options.inPreferredConfig = Bitmap.Config.ARGB_8888;
    return BitmapFactory.decodeFile(fn, options);
} catch (OutOfMemoryError ex) {
    Log.e(LOG_TAG, "Got oom exception ", ex);
    return null;
}
}

private static int computeInitialSampleSize(BitmapFactory.Options options,
    int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;

int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 :
        (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == UNCONSTRAINED) ? 128 :
        (int) Math.min(Math.floor(w / minSideLength),
        Math.floor(h / minSideLength));

if (upperBound < lowerBound) {
    // return the larger one when there is no overlapping zone.
    return lowerBound;
}

if ((maxNumOfPixels == UNCONSTRAINED) &&
        (minSideLength == UNCONSTRAINED)) {
    return 1;
} else if (minSideLength == UNCONSTRAINED) {
    return lowerBound;
} else {
    return upperBound;
}
}
Anmol317
  • 1,356
  • 1
  • 14
  • 31
0

You can use Glide for loading images and scale them down. You can add this in your Gradle file:

repositories {
  mavenCentral() // jcenter() works as well because it pulls from Maven Central
}

dependencies {
  compile 'com.github.bumptech.glide:glide:3.7.0'
  compile 'com.android.support:support-v4:25.3.1'
  annotationProcessor 'com.github.bumptech.glide:compiler:4.0.0-RC1'
}

And this could be an approach of how you can use it:

Glide.with(context)
            .load(images.get(position))
            .override((int)(thumbnailHeight * IMAGE_SCALE_FACTOR), (int)(thumbnailHeight * IMAGE_SCALE_FACTOR))
            .into(imageView);

where images is an ArrayList<String> containing urls of images (local or remote), thumbnailHeight is the height of the view containing this image (I also used the height value for width to make it squared), IMAGE_SCALE_FACTOR is a constant indicating how much your image is going to be scaled down (if you want it smaller, just use values between 0.1 and 0.9)

Brigadier
  • 886
  • 7
  • 17
  • Thank you very much, it worked! You may change in .override the two thumbnailHeight to the width and heigth. – Thomi Jul 19 '17 at 13:52