Android bitmap out of memory error (mapviewBalloons) - android

I get the famous out of memory error. But i have tried many of the suggested solutions on this problem without any luck. I understand that to prevent a bitmap to exceed the memory, you make a static variable of the drawable (Android docs). But that isn't working in my app because i have so many markers as you can see..
Does anyone have a suggestion to a solution?
for(Poi p : poiarray){
WeakReference<Bitmap> bitmap = new WeakReference<Bitmap>(p.get_poiIcon());
if(bitmap!=null){
Drawable marker = new BitmapDrawable(Bitmap.createScaledBitmap(bitmap.get(), 60, 60, true));
annotationOverLays.add(new CustomAnnotation(marker,p,this,mapView));
//mapView.getOverlays().add(new CustomAnnotation(marker,p,this,mapView));
}
}
mapView.getOverlays().addAll(annotationOverLays);
ERROR:
05-23 13:08:31.436: E/dalvikvm-heap(22310): 20736-byte external allocation too large for this process.
05-23 13:08:31.436: E/dalvikvm(22310): Out of memory: Heap Size=23111KB, Allocated=22474KB, Bitmap Size=1505KB
05-23 13:08:31.436: E/GraphicsJNI(22310): VM won't let us allocate 20736 bytes
EDIT:
I think i maybe have localized the problem.. I can trigger that outOfmemory exception if i click on several of the annotations. I use the mapViewBalloons from Here, and when i have open closed 2 several times, my app crashes with the exception. Anyone have similar problem?

There are a lot of ways to solve the out of memory exeption.
Try to set inPurgeable at your BitmapFactory.Options http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inPurgeable
or try a PurgeableBitmap.
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/PurgeableBitmap.html
Scale Images to smaller size. If you have a view with an adapter make a list with FIFO and fixed size...

I had the same problem and the following code worked for me:
public static Bitmap decodeFile(File f, boolean goodQuality){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_SIZE=100;
//Find the correct scale value. It should be the power of 2.
int scale=1;
if(!goodQuality){
while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
}
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}

Related

Bitmap size much greater than file size from which it's loaded

I'm using the following code to retrieve an bitmap from image file in android:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
However, the size of the bitmap is more than double the size of file. Eg, for a file of size 520kb, the bitmap size is around 1.3MB. Is there a way I can get the bitmap of the same size as that of file?
The bitmap size is pure memory data without compression. You can calculate the size with 4 bytes per pixel (with your settings).
Your file is probably in a compressed format like jpg. Without a compression it would take up the same space.
The reason why the bitmap is kept uncompressed in memory is basically the performance. You can read the data and work with it much faster in an uncompressed way. For example if you would like to see what color a specific pixel has, you would need to uncompress the data first. That takes time and the more pixels you check the more time it would take.
While reading the file from the storage, the uncompression just takes an ignorable amount of time compared to the complete reading process. So you will not have a big performance impact compared to "on demand" uncompression.
try like this may help you,
public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_WIDTH=WIDTH;
final int REQUIRED_HIGHT=HIGHT;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}

android-getting error out of memory with showing images

I've an imageview that shows an image everytime user run the app . the images are in drawable folder .
every so often the app crash and in the lof cat it says java.lang.outOfMemmoryError
I've lots of images, about 100 images. 100,000 Byet .
What is the solution to show these images to don't use lot of memory ?
thanks so much
To fix OutOfMemory you should do something like that:
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap=BitmapFactory.decodeStream(is,null,options);
This inSampleSize option reduces memory consumption.
Here's a complete method. First it reads image size without decoding the content itself. Then it finds the best inSampleSize value, it should be a power of 2. And finally the image is decoded.
private Bitmap decodeFile(File f){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_SIZE=70;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}

Android Bitmap OutOfMemory issue

My application would have more than 350 images which would be decoded from database. I create bitmap from image data and scale them based on device screen resolution. When I tried to hold all of these bitmaps into memory, I was facing outOfMemory exception. Then BitmapFactory.Options.inPurgeable has been recommended in various places as a way to avoid OutOfMemoryExceptions.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
options.inInputShareable = true;
Bitmap bitmap = BitmapFactory.decodeByteArray(imagaeData, 0, size, options);
...
..
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, true);
I am caching this scaled bitmap to HashMap and using it for image view. Again I am facing OutOfMemory exception while loading the bitmaps to memory. I don't understnad whether the inPurgeable is working in my case. I am wondering will the scaled bitmap have reference to bytes array. As I am using scaled bitmap, will it have the effect of the inPurgeable option used in decodeByteArray. I am not able to figure out how to handle this bitmap memory issue. Appreciate your help.
350 images are quite a lot. Are you sure that you need them all at once?
Also: as you create a scaled bitmap, you have them in memory twice -> 700 images in memory is way way way too much. You should check if it would be better to use inScale on the option to reduce it to 350 again plus reduce the memory footprint.
I still think that even in optimized ways 350 images are just too much. You should consider a lazy loading solution.
You may try BitmapFactory.Options.inScaled & BitmapFactory.Options. inScreenDensity to get the scaled bitmap.
And you need a better way to cache bitmap in memory. You'd better hold WeakReference of the Bitmap in HashMap for the bitmap, and you can switch to LinkedHashMap for a simple LRU cache implementation.
You don't really need cache all the images, since they'll never get a chance to be displayed in one screen.
Wow, it sounds crazy to try and keep 350 bitmaps in memory at once. Even if they were small I wouldn't recommend it. Surely you won't be able to show all these bitmaps at once, so whats the point of keeping all of them in memory at the same time?
You really should look into using something like Square's Picasso lib for handling image loading and scaling. Picasso handles "ImageView recycling and download cancelation in an adapter", "automatic memory and disk caching" and finally also "complex image transformations with minimal memory use".
Use this method to reduce the image size first (file points to a photo on SD card)
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1=new FileInputStream(f);
BitmapFactory.decodeStream(stream1,null,o);
stream1.close();
//Find the correct scale value. It should be the power of 2.
// maximum size is 50
final int REQUIRED_SIZE=40;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<=REQUIRED_SIZE || height_tmp/2<=REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
FileInputStream stream2=new FileInputStream(f);
Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
// Here is how to call the above method
String path = "/mnt/sdcard/DCIM/camera/IMG_2001.jpg";
Drawable background = hash_map.get(path);
if (background == null) {
try {
Bitmap bitmap = decodeFile(new File(path));
background = new BitmapDrawable(bitmap);
if (hash_map.size() > 600) {
// to prevent HashMap from growing too large.
hash_map.clear();
}
hash_map.put(path, background);
} catch (Throwable e) {
// in case there is an exception, like running out of memory.
if (e instanceof OutOfMemoryError) {
hash_map.clear();
}
}
}

Out of Memory error with Bitmap

During runtime, I am trying to put an image in the surface view. When I tried using the image from the Drawable folder I got Out of memory error. After a quick search in the stackoverflow, I found that there will be some relief if we access the image from the asset folder. But still I get the Out of memory error during runtime.
I have analyzed and found that scaling will help in resolving this kind of memory related issues. The thing is that I have the image size of 1280 x 720 and the device size also the same. Hence I feel like the scaling will not have any effect.
As we have experts in this community, I would appreciate if you can help me with some suggestions/examples to resolve this kind of issue.
Scenario 1:
Using the Bitmap from Drawable folder.
backgoundImage = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.backgroundhomepage), (int) dWidth, (int) dHeight, true);
/***********************************************************************************************************************************************************
1. To get the image from asset library
**************************************************************************************************************************************************************/
public Bitmap getAssetImage(Context context, String filename) throws IOException {
AssetManager assets = context.getResources().getAssets();
InputStream buffer = new BufferedInputStream((assets.open("drawable/" + filename + ".png")));
Bitmap bitmap = BitmapFactory.decodeStream(buffer);
return bitmap;
}
Scenario 2:
Using the Bitmap from Assets folder
backgoundImage = Bitmap.createScaledBitmap(getAssetImage(context,"backgroundhomepage"), (int) dWidth, (int) dHeight, true);
OutofMemory occurs when your app exceeds memory allocated in heap. The bitmap is too large to fit in memory ie heap. In such a case you run out of memory. You need to scale down the bitmap and then use the same. For that check the link below
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html.
There is also a blog # http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html (avoiding memory leaks)
public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_WIDTH=WIDTH;
final int REQUIRED_HIGHT=HIGHT;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
Quoting from the docs
The BitmapFactory class provides several decoding methods (decodeByteArray(), decodeFile(), decodeResource(), etc.) for creating a Bitmap from various sources. Choose the most appropriate decode method based on your image data source. These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.Options class.
Setting the inJustDecodeBounds property to true while decoding avoids memory allocation, returning null for the bitmap object but setting outWidth, outHeight and outMimeType. This technique allows you to read the dimensions and type of the image data prior to construction (and memory allocation) of the bitmap.
Also check this link for memory management.
https://www.youtube.com/watch?v=_CruQY55HOk
Got a quick Solution
<application
android:largeHeap="true" >
put into appplication tag in manifest file.
You can use the following code to load the bitmap from file:
private Bitmap decodeFile(File f,int req_Height,int req_Width){
try {
//decode image size
BitmapFactory.Options o1 = new BitmapFactory.Options();
o1.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o1);
//Find the correct scale value. It should be the power of 2.
int width_tmp = o1.outWidth;
int height_tmp = o1.outHeight;
int scale = 1;
if(width_tmp > req_Width || height_tmp > req_Height)
{
int heightRatio = Math.round((float) height_tmp / (float) req_Height);
int widthRatio = Math.round((float) width_tmp / (float) req_Width);
scale = heightRatio < widthRatio ? heightRatio : widthRatio;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
o2.inScaled = false;
return BitmapFactory.decodeFile(f.getAbsolutePath(),o2);
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
It should resolve your out of memory exception.
Link here has a good detailed explanation of your answer.

Resizing images in android and iOS

We have an application, running on iOS and on Android. There is a function in app, that loads images to server with specific size ( < 2 mb) So before loading images to the server I need to resize it to reduce image size to successfuly load it to the server.
Is there any solution to make photos compatible with the most part of screen sizes (I need to show full size of image on the screen), running on Android and iOs (no iPad)?
thanks
try this code
private Bitmap decodeBitmapFile(File f,int size,int scal){
try {
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
final int REQUIRED_SIZE=size;
int scale=scal;
while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}

Categories

Resources