1

I'm developing an Android game consisting of many images as sprites.

When I load the images the following way:

public static Bitmap loadBitmap(int resId) {  
    return BitmapFactory.decodeResource(getResources(), resId, options);
}

everything works perfectly fine.

When I try to down-scale or up-scale the bitmap with this code:

public static Bitmap loadBitmap(int resId) {
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId, options);
    Matrix matrix = new Matrix();
    matrix.postScale(0.8f, 0.8f);
    Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    bitmap.recycle();
    bitmap = null;
    return scaledBitmap;
}

the application crashes with the following exception:

2211840-byte external allocation too large for this process.  
Out of memory: Heap Size=4935KB, Allocated=2549KB, Bitmap Size=18463KB  
VM won't let us allocate 2211840 bytes

Why is the scaling causing OutOfMemory exception? I even try to recycle the original image in order to save some space. I'm not using Bitmap.createScaledBitmap(...) intentionally, since this method does memory leaking internally (as explained in other online resources).

Thank you in advance,
Zlatko

Bart
  • 147
  • 12
  • Also see [How do I scale a streaming bitmap in-place without reading the whole image first?](https://stackoverflow.com/q/7051025/608639) – jww Sep 02 '18 at 15:42

3 Answers3

1

You are probably just very close to the memory limit. It looks like you are creating a pretty large bitmap (and I'm not sure why you are making it the same size as the original bitmap). From the log, you have used 25MB of Java allocations, and 18MB of bitmap allocations, so you are basically right up against the 48MB heap limit.

Also I think it is very unlikely that createScaledBitmap() leaks. All it does is basically what you are doing here.

hackbod
  • 90,665
  • 16
  • 140
  • 154
  • Why is it that the first code snippet never results in a OOM exception? As a matter of fact, in the second snippet I'm scaling the original bitmap to 80% of its size. Allocated, there is 2.5MB and not 25MB – Bart May 28 '11 at 00:54
0

You should try to use the variable "inSampleSized" in the BitmapFactory.Options class. This will scale without using excess memory.

http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize

Amandeep Grewal
  • 1,801
  • 3
  • 19
  • 30
  • "inSampleSize" is an int variable >=1, therefore I don't have fine control over the factor of scaling. The game requires specific up- and down-scaling factors, e.x. 0.7688 – Bart May 28 '11 at 21:01
  • Do you require saving the bitmap when you resize? Why don't you just apply a matrix on the Canvas you are drawing onto when drawing the Bitmap. The larger bitmap will be in memory but it may use less memory this way as another Bitmap does not need to be allocated. – Amandeep Grewal May 30 '11 at 14:19
0

I guess you´re really close to the heap limit. In your function, you basically are instantiating a second Bitmap, which roughly leads to doubling your memory (Bitmaps are very large). If you´re on an OS earlier than Honeycomb, it´s also misleading to look at memory values, which are printed out somewhere. iirc, Bitmaps are held directly on the system memory heap, whereas everything other is held on the vm heap (and these are the values you see -> 2,5MB). However, the memory for Bitmap allocations also counts in for the memory heap limit. :/

I suggest you have a look at this Google I/O Session: http://www.youtube.com/watch?v=_CruQY55HOk

I think your problem can only be solved by bringing down the resolution of your Bitmap or by using some scale function, that doesn´t instantiate a new Bitmap and modifies the existing one (like the one mentioned by AmandeepGrewal).

stk
  • 6,311
  • 11
  • 42
  • 58
  • Thanks for the link. It's really educational. As for the problem, I'm not able to bring down resolution since it should be strictly defined. Also, I tried solution with caching all already-loaded resources. When I'm not image-recycling, I end up with OutOfMemory. When I'm recycling, then I get SIGNAL 11 (WIN_DEATH) native error hard to debug. It's getting really frustrating... – Bart May 28 '11 at 21:06