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.
Related
I am trying to implement the code below converting a image path into a bitmap to display on my activity. I am getting the below error. I have tried a bunch of different solutions but none are working
Strange out of memory issue while loading an image to a Bitmap object
Android: Resize a large bitmap file to scaled output file
OutOfMemoryError: bitmap size exceeds VM budget :- Android
Error:
E/dalvikvm-heap(19252): 12742656-byte external allocation too large for this process.
for(int i = 0; i < numItems; i++) {
File imgFile = new File(photoPaths.get(i));
if(imgFile.exists())
{
images[i] = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
}
You may consider loading them in a more just-in-time kind of approach, or using the inSampleSize option of the bitmap factory (i.e., you'd pass a BitmapFactory.Options in to the factory with inSampleSize set to, ideally, a power of 2). Also make sure you set inPurgeable true.
In the event that you are pulling these images from the MediaStore's ContentProvider, you can also use thumbnails.
Perhaps you can tell us more about your use case so we can better help.
You're trying to load multiple large bitmaps, at least one of which is ~12MB. They're too large. The solutions you posted DO work. Resize your bitmaps to something much smaller, especially as you're just displaying the bitmaps on the screen.
I have tried working with a bit of code to decode a file from SD and then edit it. Because of this editing that needs to be done, keeping a higher scaled image is important. Some phones run into memory issues, whereas others have enough room in their heap to continue the decode without a set option.
//the following is ending a process in which a photo is taken and saved
//under "/sdcard/folder/photo.png"
FileOutputStream fos= new FileOutputStream(photo.getPath());
fos.write(jpeg[0]);
fos.close();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap originalFile = BitmapFactory.decodeFile("/sdcard/folder/photo.png",options);
I am basically looking into whether there is a way to almost set an if statement to put the option into place (if needed) otherwise continue without it.
As a workaround, wrap decoding into a try-catch and if "out of memory" exception happen, just catch it and try decode with properly set inSampleSize.
However, this looks more like a hack than a solution.
Basically, you need to know how much memory your decoded bitmap will take and how much memory is available for your application's heap to grow in the system right now.
First is easy to find out: width*height*4 bytes (by default decoding is in ARGB8888).
But I have no idea how to get the heap's memory size.
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.
I read many discussions about the inSampleSize OutOfMemory dilemma.
Cannot get a good solution so i ask a question about it.
Im currently loading a bitmap with inSampleSize=4.
That will give me a Bitmap with the size 648x388.
Original On disk size is 2592x1592.
Im writing text on 648x388 bitmap and saving it back to disk.
Im writing on the 648x388 because the 2592x1592 give me OutOfMemory .
The way it works is that there can be 1-10 648x388 Bitmaps to be saved in a while loop.
I want to change this loop to save 1-10 2592x1592 Bitmaps.
How can i securely load the 2592x1592?
I don care about the resolution going down 60% or more.
As long as the Bitmap has the same size 2592x1592.
Is there a way to maybe keep the size but make Bitmap thinner,
removing color without making quality bad.
My first thought was going something like this to get the biggest bitmap i could get:
I have not tested this but get a feeling it's a bad way
boolean work = true;
int insample = 2;
BitmapFactory.Options options = new BitmapFactory.Options();
while(work){
try{
options.inSampleSize = insample;
bitmap = BitmapFactory.decodeFile(filePath,options);
work = false;
}catch(Exception e){
insample++;
}
}
any help would be grate.
Image processing requires a lot of memory. you cant use the whole bitmap and just modify it on your phone. use a web service for that. upload, process, download. sorry there is no other way a decoded bitmap just takes a lot of memory.
And by the way you cant catch an outOFMemory Exception. the app just crashes.
There's a hard limit on process size in Android and a 4 mega-pixel image at four bytes a pixel will hit it all by itself (on many devices), without any room for your program.
I think you are going to need to do one of two things: Create a web service to do the image processing on a server/in the cloud; or learn to do your image processing "on-the-fly" by manipulating the data directly instead of using a bitmap.
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);