Image is always making problem for me always :(.
java.lang.OutOfMemoryError: bitmap size exceeds VM budget - android is the main problem even if i use very small image.
Please suggest me some tips in using Image. (link, tutorials, sample projects etc...)
Some of my quires are
Which should i prefer Drawable or bitmap
BitmapFactory.decodeFile or Drawable.createFromPath
BitmapFactory.decodeStream or Drawable.createFromStream
How to retain Drawable and Bitmap while rotating.
Is it a good idea to save or pass Drawable or Bitmap through intent
that all depends on what exactly you want to do with your image. bitmapfactory is for creating bitmaps. and drawable objects are used when you want to draw something :)
what do you want to do with your bitmap after you have created it in the memory?
as for rotating, you should take care of onRestoreInstanceState and onSaveInstanceState. something like this:
private static final String PHOTO_TAKEN = "photo_taken";
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState.getBoolean(PHOTO_TAKEN)) {
// do something if you have your pic here
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean(PHOTO_TAKEN, mPhotoTaken); // saving the state of the image (if the photo is taken or not in this case)
}
as for passing through extras... i bet it's a bad idea as you already getting outofmemory exception.... you can pass a reference to that image, like ID of path or something else.
UPDATE:
in one of the projects i was trying to show the image taken from the cam in an ImageView control ion my activity and got that outofmemory exception. the reason was that it was putting the whole big image into memory. the workaround was quite simple: i decreased the image size:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeFile(mImagePath, options);
To avoid out of memory error we can use BitmapRegionDecoder ( to decode the original image which is larger than maximum texture limit 2048x2048 ) or we can decode it by specifying the coordinates from the original bitmap. (for e.g coordinates of each quarter)
Related
I'm running into issues with the images in my gallery being much much larger than I need them to be.
I've looked for ways to reduce their size before I actually pull them in, but I'm just not quite putting it together as most of what I'm finding deals with BitMap resources and not a BitMap that already exists in the gallery.
So, basically, I am getting the image like so,
imageBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
But before I actually assign it to my BitMap var over there I need to scale it down to a reasonable size for a phone.
Any help with understanding what is going on here better is appreciated.
getBitmap() is a weak convenience method. Its body is a whopping four lines of code:
public static final Bitmap getBitmap(ContentResolver cr, Uri url)
throws FileNotFoundException, IOException {
InputStream input = cr.openInputStream(url);
Bitmap bitmap = BitmapFactory.decodeStream(input);
input.close();
return bitmap;
}
This is why I don't bother teaching people about it.
IMHO, the best solution is for you to use one of the many image-loading libraries available for Android, such as Picasso. Most of the good ones can load from a Uri and handle your resizing as part of the operation, doing the heavy lifting on a background thread.
If, for whatever reason, you want to do all that work yourself, call BitmapFactory.decodeStream() with a BitmapFactory.Options object. In particular, set inSampleSize to indicate that you want the image to be resampled as part of reading it, so you wind up with a smaller Bitmap taking up less heap space.
I am trying to change wallpaper using a widget.
I use the code below to achieve that:
But there is an certain delay every time the code is executed.
Is there any way to avoid this delay.
...
WallpaperManager wallpaperManager = WallpaperManager.getInstance (context);
Bitmap bitmap = BitmapFactory.decodeStream (new FileInputStream (file));
//here #file is fetched from a phone storage
wallpaperManager.setBitmap (bitmap);
...
I see four options which might help here:
Reduce the size of the bitmap before saving it to the file
Preload the bitmap (well, if possible)
Do all this asyncronous
Make sure your heap is as empty as possible before loading the bitmap. If android has to free heap while decoding a large bitmap it will slow down noticeably
Scenario:
A Fragment
A gridview which displays images from external-storage/downloads from the web
An Adapter for the gridview which uses an xml layout containing an ImageView and a TextView inside a FrameLayout
Inside getView the adapter downloads the image and sets it as resource for the bitmap
After the user is done with the fragment, the fragment is removed.
My concern:
We all know that android is prone to OoM errors, especially when working with bitmaps, even if when they are scaled down.
When the fragment is removed, like onPause should I parse all the items of the GridView and:
remove callbacks for image drawable
recyle the bitmpa drawable ?
Is this needed to prevent memory leaks ?
If you don't need a full size image, I recommend you to use sampled images.
options.inSampleSize = calculateInSampleSize();
options.inJustDecodeBounds = false;
And I use the following tricky code in my own project on decoding files to bitmaps.
public static Bitmap decodeFile(String pathName, BitmapFactory.Options opts) {
for (int i = 0; i < 5; ++i) {
try {
return BitmapFactory.decodeFile(pathName, opts);
}
catch (OutOfMemoryError e) {
System.gc();// Retry with running gc.
}
}
return BitmapFactory.decodeFile(pathName, opts);
}
As I said, my main concern was related to usage of already scaled down bitmaps, but in the same time handling a lot of memory caching of other images. This could be a problem for instance on big screen devices, where an image can be scaled to 1080px and its footprint in memory is not small. I also had to stack some fragments containing images for future use.
This forced the app to run into out of memory after a while. The fix I applied for now is to allow large memory use by android:largeHeap="true"
I require displaying many images in my application. These being jpgs and pngs and i'm loading them inside ImageViews like so:
tile.setImageResource(R.drawable.tile_highlight);
I am currently having OutOfMemory problems (java.lang.OutOfMemoryError: bitmap size exceeds VM budget)
I've searched and found some other posts, they all suggest that you should recycle the bitmap of an ImageView manually, like so: ((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle(); which will dump it from memory.
BUT in my case, being that i'm not using setBitmap() to load the images onto the ImageView objects, when i try and run the above code, it returns NullPointerException, more precisely, the method getBitmap() returns null, there is no bitmap ?!?!
Do i need to go back in my code and change the way i load all the images in the ImageViews, and then try with the recycle() method? Or how can i free up the memory so it doesn't crash anymore?
EDIT
I've tried something like so: imageView.setImageResource(-1); in hopes it will remove the image from memory and replace it with ... null or something, but it seems it doesn't help the cause.
It would be helpful if you could post some of your code. Specifically, how you're setting the images of the ImageView objects. If you're not using bitmaps, I would expect that getBitmap() will return null. However, if you're using another sort of Drawable or otherwise to set the image, there's likely a similar route to take that doesn't involve bitmaps.
EDIT:
Alright, give this a shot. You can create a Bitmap from a resource like this:
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.image);
Then, use the bitmap like this, considering img is your ImageView:
img.setImageBitmap(bm);
//Do some stuff with it, then when memory gets low:
((BitmapDrawable)img.getDrawable()).getBitmap().recycle();
Of course, this is considering that you're in an activity. If not, you'll have to get a handle on the context and replace getResources() with context.getResources().
If you want to set an image from drawable to ImageView, Do not use ImageView.setImageResource(int resId) directly with drawable id. Instead get Scaled down bitmap(if applicable) and set it to imageView. like this:
this works for me.
iv.setImageBitmap(decodeResource(getResources(), R.drawable.big_image));
private static Bitmap decodeResource(Resources res, int id) {
Bitmap bitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
for (options.inSampleSize = 1; options.inSampleSize <= 32; options.inSampleSize++) {
try {
bitmap = BitmapFactory.decodeResource(res, id, options);
Log.d(TAG_LOG, "Decoded successfully for sampleSize " + options.inSampleSize);
break;
} catch (OutOfMemoryError outOfMemoryError) {
// If an OutOfMemoryError occurred, we continue with for loop and next inSampleSize value
Log.e(TAG_LOG, "outOfMemoryError while reading file for sampleSize " + options.inSampleSize
+ " retrying with higher value");
}
}
return bitmap;
}
source: https://codingjunkiesforum.wordpress.com/2014/06/12/outofmemory-due-to-large-bitmap-handling-in-android/
try
((BitmapDrawable)im.getBackground()).getBitmap().recycle();
I think you should display images with lower resolution. This would resolve the OOM problem. You can also read Android Developer Guideline link
OutOfMemory error comes when you dont free bitmap once its being used(may be large size) so to prevent this we should keep in mind of re-sizing,taking weakreferences etc.
but there are good libraries available which is taking care all problem one of them is Picasso. please have a look at-
loading images using Picasso
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.