Android Bitmap freeing memory - none of this works - android

I get "bitmap size exceeds VM budget", eventually with my app. So I added all of these things to help alleviate the increasing memory footprint
BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[32*1024];
options.inDither=false; //Disable Dithering mode
options.inPurgeable=true; //Tell to gc that whether it needs free memory, the Bitmap can be cleared
options.inInputShareable=true; //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
options.inPreferredConfig = Bitmap.Config.RGB_565;
Drawable pulled = BitmapDrawable.createFromResourceStream(null, null, conn.getInputStream(), "galleryImage", options);
I am also using weakhashmaps, recycling, System.gc()
and all this successfully PROLONGES the crash. where a device with a 32M heap initially would have only been able to handle a few images before crashing, now it can handle a dozen, but this doesn't fix the problem. The problem is the BitMap method is leaking memory and simply will not clear.
How do I fix this? The images are of size 256x357

If you want to really make sure those Bitmaps are freed, you have to call recycle() on those Bitmaps that are no longer needed. If you need all of them, then recycle least recently used ones (and re-load them, again when needed).

You should try to use drawable.setCallback(null); when you don't need a drawable anymore, because even if you're using a WeakHashMap, they can still be attached to the context through their callback attribute.
See this

I was dealing with ImageView and i solved the memory problem using imageView.clearAnimation(); before to assign the new bitmap and now i have no memory error.

Related

Make expression that can handle large bitmaps

Like many others I have the anoying VM budget problem. I am getting files from the sdcard and I decode it and comprimizes them using:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
The problem is that i get the bitmap each time i call the onCreate method. So after turning phone or starting the activity a couple of times it crashes. The only method I can find to avoid this is:yourBitmap.recycle(), but you can not catch a recycled Bitmap.
I need an expression that still manage to show the the bitmap even after it would normaly crashed on VM budget. I am showing the bitmap as a drawable, so the classic unbindDrawables solotion does not work. I need an expression that eighter comprimices the Bitmap to almost nothing, or that recycles and shows a new Bitmap of the same size.
try reading this:
http://developer.android.com/training/displaying-bitmaps/index.html
and watching this:
http://www.google.com/events/io/2011/sessions/memory-management-for-android-apps.html
also , about drawables, see that you don't have any references to them after they are not needed . drawables can cause memory leaks.

Bitmap Size Exceed VM budget In android

In my android app i have set the image on ImageView capture by camera. its working fine. but when i capture image and back to the screen with setting that image on imageview and if i do this 3 to 4 time i got This ERROR BITMAP SIZE EXCEEDS VM BUDGETS ...................please need any solution for it.
this is my code below :
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
options.inTempStorage = new byte[16 * 1024];
image_from_camera.setImageBitmap(BitmapFactory.decodeFile(
"/sdcard/"+chore_string+".jpg", options));
i have done using bitmap.recycle(); or System.gc();
but this is not working . i need to have free the memory from bitmap when again camera button click to take second picture in app. PLEASE NEED ANY HELP........
THANKS. ...
increasing the value of the inSampleSize will decrease the memory overhead required to load the image. Change it to 8,12 or 16... and the image should eventually load but it might not look very good.
However, it seems like you might be using a good bit of memory prior to the load.
Use System.getRuntime() to get the runtime and then see what your max memory, total memory and free memory are to better understand how much space you have.
It's possible you are leaking memory prior to this allocation.
http://developer.android.com/reference/java/lang/Runtime.html
also (annoyingly) if you are using a device that can't run android 3.0 not all of the memory used will show up in the runtime calls. consider using a 3.0 device to more fully understand the memory usage.

Scaling images in Android causes OutOfMemory exception

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
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.
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
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).

Android out of memory on image capture

I have an Activity which takes photos (with full possible resolution, so quite large), the application have then the chance to analyze them. Only one photo is handled at a time. The problem is that I run in to a "Out of memory" after 4 - 5 photos. I see
dalvikvm-heap Out of memory on a 5070745-byte allocation
(the byte size varies) followed by
Camera-JNI Couldn't allocate byte array for JPEG data
My application does not crash but as it appears to me the Camera simply becomes unable to deliver the images from this point on. I pay attention to memory usage in my application but here it seems that there is a memory leak somewhere outside and I'm asking me how can I cope with this. Any solution approaches existing for this?
This may not be exactly what you are trying to do, but in order to display multiple large pictures (4-6 MB) on a grid view, I found this code to create a smaller bitmap with lower quality, to avoid out-of-memory situations:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 5;
options.inPurgeable = true;
options.inInputShareable = true;
Bitmap bm = BitmapFactory.decodeFile("/sdcard/myapp/" + filesFound.get(position), options);
The options are the important part, and by varying the settings, I managed to take memory down from where it would crash, to around 28MB when I started using the inSampleSize. It further went down with the inPurgeable and inInputShareable settings set to true. My activity is still sluggish, but it's much better.
For your application, if it can analyze a bitmap, the above code may shrink down the memory usage enough to make it work. I'm still new to Android, so it's possible this may not work at all.. ;-).
Regards,
Kevin
Since you run out of memory after 4-5 pictures you probably arent calling yourBitmap.recycle(); after it has been saved to the SD-card?
Also in the onPictureTaken() method you could save the tempData from the picture into a bitmap using the Bitmap.Config.RGB_565 instead of ARGB(default) if you don't need the alpha channel.
// Create options to help use less memory
Options opt = new Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
// Decode the tempdata into a bitmap, with the options as the last argument
bitmapFromRawCameraTempData = BitmapFactory.decodeByteArray(rawCameraTempData, 0, rawCameraTempData.length, opt);

Android: How does Bitmap recycle() work?

Let's say I have loaded an image in a bitmap object like
Bitmap myBitmap = BitmapFactory.decodeFile(myFile);
Now, what will happen if I load another bitmap like
myBitmap = BitmapFactory.decodeFile(myFile2);
What happens to the first myBitmap? Does it get Garbage Collected or do I have to manually garbage collect it before loading another bitmap, eg. myBitmap.recycle()?
Also, is there a better way to load large images and display them one after another while recycling on the way?
The first bitmap is not garbage collected when you decode the second one. Garbage Collector will do it later whenever it decides. If you want to free memory ASAP you should call recycle() just before decoding the second bitmap.
If you want to load really big image you should resample it. Here's an example: Strange out of memory issue while loading an image to a Bitmap object.
I think the problem is this: On pre-Honeycomb versions of Android, the actual raw bitmap data is not stored in VM memory but in native memory instead. This native memory is freed when the corresponding java Bitmap object is GC'd.
However, when you run out of native memory, the dalvik GC isn't triggered, so it is possible that your app uses very little of the java memory, so the dalvik GC is never invoked, yet it uses tons of native memory for bitmaps which eventually causes an OOM error.
At least that's my guess. Thankfully in Honeycomb and later, all bitmap data is stored in the VM so you shouldn't have to use recycle() at all. But for the millions of 2.3 users (fragmentation shakes fist), you should use recycle() wherever possible (a massive hassle). Or alternatively you may be able to invoke the GC instead.
You will need to call myBitmap.recycle() before loading the next image.
Depending on the source of your myFile (E.g. if it is something you have no control over the original size), when loading an image instead of just simply resampling some arbitrary number, you should scale the image to the display size.
if (myBitmap != null) {
myBitmap.recycle();
myBitmap = null;
}
Bitmap original = BitmapFactory.decodeFile(myFile);
myBitmap = Bitmap.createScaledBitmap(original, displayWidth, displayHeight, true);
if (original != myBitmap)
original.recycle();
original = null;
I cache the displayWidth & displayHeight in a static that I initialized at the start of my Activity.
Display display = getWindowManager().getDefaultDisplay();
displayWidth = display.getWidth();
displayHeight = display.getHeight();
Once bitmap had been loaded in memory , in fact it was made by two part data.
First part include some information about bitmap , another part include information about pixels of bitmap( it is maked up by byte array).
First part exisits in Java used memory, second part exisits in C++ used memory. It can use each other's memory directly.
Bitmap.recycle() is used to free the memory of C++.
If you only do that,the GC will collection the part of java and the memory of C is always used.
Timmmm was right.
according to :
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
In addition, prior to Android 3.0 (API Level 11), the backing data of a bitmap was stored in native memory which is not released in a predictable manner, potentially causing an application to briefly exceed its memory limits and crash.

Categories

Resources