Android: Strange out of memory issue?

May be the answer mentioned on this site might solve the issue... BitmapFactory. Options options = new BitmapFactory.Options(); options. InTempStorage = new byte16*1024; bitmapImage = BitmapFactory.

DecodeFile(path,opt).

1 Tried this solution. Unfortunately no effect. Still OutOfMemory for large photos.

– Fedor Jul 27 '10 at 0:39 2 I also tried this and still get an OutOfMemory exception too. – stealthcopter Sep 4 '10 at 22:36 7 I don't think this helps, and the reason I don't is because I read the source code for decodeFile and the source code does this itself if you don't. – Max Howell Sep 8 '10 at 13:34 3 didnt, worked for me!

– nicky Jan 20 at 22:37 3 I tried that, and this approach is not working. – Rajnikant Feb 18 at 10:05.

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. //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; 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 width_tmp=o. OutWidth, height_tmp=o. OutHeight; int scale=1; while(true){ if(width_tmp/2DecodeStream(new FileInputStream(f), null, o2); } catch (FileNotFoundException e) {} return null; }.

5 Note that 10 may not be the best value for inSampleSize though, the documentation suggests using powers of 2. – Mirko N. May 28 '10 at 11:59 2 I'm facing the same problem as Chrispix, but I don't think the solution here really solves the problem, but rather sidesteps it.

Changing the sample size reduces the amount of memory used (at the cost of image quality, which is probably okay for an image preview), but it will not prevent the exception if a large enough image stream is decoded, of if multiple image streams are decoded. If I find a better solution (and there may not be one) I'll post an answer here. – Flynn81 Jul 8 '10 at 15:19 1 You only need an appropriate size to match the screen in pixel density, for zooming in and such you can take a sample of the image at a higher density.

– stealthcopter Aug 8 '10 at 22:43 1 instead of scale++ you should use scale *= 2; – Roel Spilker Nov 10 '10 at 10:44 1 Terrific. Its working very good. Thanks Fedor – androidGuy Mar 30 at 12:08.

I've made a small improvement to Fedor's code. It basically does the same, but without the (in my opinion) ugly while loop and it always results in a power of two. Kudos to Fedor for making the original solution, I was stuck until I found his, and then I was able to make this one :) private Bitmap decodeFile(File f){ Bitmap be = null; try { //Decode image size BitmapFactory.

Options o = new BitmapFactory.Options(); o. InJustDecodeBounds = true; FileInputStream fis = new FileInputStream(f); BitmapFactory. DecodeStream(fis, null, o); fis.close(); int scale = 1; if (o.

OutHeight > IMAGE_MAX_SIZE || o. OutWidth > IMAGE_MAX_SIZE) { scale = (int)Math. Pow(2, (int) Math.

Round(Math. Log(IMAGE_MAX_SIZE / (double) Math. Max(o.

OutHeight, o. OutWidth)) / Math. Log(0.5))); } //Decode with inSampleSize BitmapFactory.

Options o2 = new BitmapFactory.Options(); o2. InSampleSize = scale; fis = new FileInputStream(f); be = BitmapFactory. DecodeStream(fis, null, o2); fis.close(); } catch (IOException e) { } return b; }.

6 Yes you're right while is not so beautiful. I just tried to make it clear to everyone. Thanks for your code.

– Fedor Aug 24 '10 at 1:32 1 This (and Fedor's code) helped point me in the right direction. Thanks! – Jake Basile Sep 23 '10 at 13:38 3 @Thomas Vervest - There's a big problem with that code.

^ doesn't raise 2 to a power, it xors 2 with the result. You want Math. Pow(2.0, ...).

Otherwise, this looks good. – DougW Oct 13 '10 at 7:42 1 Ooh, that's a very good one! My bad, I'll correct it immediately, thanks for the reply!

– Thomas Vervest Oct 26 '10 at 9:20 1 You are creating two new FileInputStreams, one for each call to the BitmapFactory.decodeStream(). Don't you have to save a reference to each of them so that they can be closed in a finally block? – matsev Feb 15 at 8:21.

You are most likely suffering from this Android bug: code.google.com/p/android/issues/detail?... The bug report contains a testcase.

1 It has been declined :( – DeRagan Nov 12 '10 at 9:17.

I have a much more effective solution which does not need scaling of any sort. Simply decode your bitmap only once and then cache it in a map against its name. Then simply retrieve the bitmap against the name and set it in the ImageView.

There is nothing more that needs to be done. This will work because the actual binary data of the decoded bitmap is not stored within the dalvik VM heap. It is stored externally.So every time you decode a bitmap, it allocates memory outside of VM heap which is never reclaimed by GC To help you better appreciate this, imagine you have kept your image in the drawable folder.

You just get the image by doing a getResources(). GetDrwable(R.drawable.). This will NOT decode your image everytime but re-use an already decoded instance everytime you call it.

So in essence it is cached. Now since your image is in a file somewhere (or may even be coming from an external server), it is YOUR responsibility to cache the decoded bitmap instance to be reused any where it is needed. Hope this helps.

And then cache it in a map against its name. " How exactly do you cache your images? – Vincent Apr 27 at 15:38 Have you actually tried this?

Even though the pixel data is not actually stored within the Dalvik heap, its size in native memory is reported to the VM and counted against its available memory. – ErikR Jun 10 at 19:45 @Vincent I think its not hard to store them in a Map. I would suggest something like HashMap map, where the Key can be a String of the source or anything that makes sense for you.

Lets assume you take a path as KEY, you store it as map. Put(Path, Bitmap) and recieve it through map. Get(Path) – Rafael T Jun 29 at 11:58 you prob would want to use HashMap> if you are implementing an image Cache otherwise you may run out of memory anyway - also I don't think that "it allocates memory outside of VM heap which is never reclaimed by GC" is true, the memory is reclaimed as I understand just may be a delay, which is what bitmap.recycle() is for, as a hint to reclaim the mem early... – Dori Jul 1 at 8:54.

It seems that this is a very long running problem, with a lot of differing explanations. I took the advice of the two most common presented answers here, but neither one of these solved my problems of the VM claiming it couldn't afford the bytes to perform the decoding part of the process. After some digging I learned that the real problem here is the decoding process taking away from the NATIVE heap.

See here: BitmapFactory OOM driving me nuts That lead me to another discussion thread where I found a couple more solutions to this problem. One is to callSystem.gc(); manually after your image is displayed. But that actually makes your app use MORE memory, in an effort to reduce the native heap.

The better solution as of the release of 2.0 (Donut) is to use the BitmapFactory option "inPurgeable". So I simply added o2. InPurgeable=true; just after o2.

InSampleSize=scale;. More on that topic here: Is the limit of memory heap only 6M? Now, having said all of this, I am a complete dunce with Java and Android too.So if you think this is a terrible way to solve this problem, you are probably right.

;-) But this has worked wonders for me, and I have found it impossible to run the VM out of heap cache now. The only drawback I can find is that you are trashing your cached drawn image. Which means if you go RIGHT back to that image, you are redrawing it each and every time.

In the case of how my application works, that is not really a problem. Your mileage may vary.

InPurgeable fixed OOM for me. – Artem Russakovskii Oct 4 at 20:10.

I had this same issue and solved it by avoiding the BitmapFactory. DecodeStream or decodeFile functions and instead used BitmapFactory. DecodeFileDescriptor decodeFileDescriptor looks like it calls different native methods than the decodeStream/decodeFile.

Anyway what worked was this (note that I added some options as some had above, but that's not what made the difference. What is critical is the call to Bitmap. DecodeFileDescriptor instead of decodeStream or decodeFile): private void showImage(String path) { Log.

I("showImage","loading:"+path); BitmapFactory. Options bfOptions=new BitmapFactory.Options(); bfOptions. InDither=false; //Disable Dithering mode bfOptions.

InPurgeable=true; //Tell to gc that whether it needs free memory, the Bitmap can be cleared bfOptions. 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 bfOptions. InTempStorage=new byte32 * 1024; File file=new File(path); FileInputStream fs=null; try { fs = new FileInputStream(file); } catch (FileNotFoundException e) { //TODO do something intelligent e.printStackTrace(); } try { if(fs!

=null) bm=BitmapFactory. DecodeFileDescriptor(fs.getFD(), null, bfOptions); } catch (IOException e) { //TODO do something intelligent e.printStackTrace(); } finally{ if(fs! =null) { try { fs.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //bm=BitmapFactory.

DecodeFile(path, bfOptions); This one causes error: java.lang. OutOfMemoryError: bitmap size exceeds VM budget im. SetImageBitmap(bm); //bm.recycle(); bm=null; } I think there is a problem with the native function used in decodeStream/decodeFile.

I have confirmed that a different native method is called when using decodeFileDescriptor. Also what I've read is "that Images (Bitmaps) are not allocated in a standard Java way but via native calls; the allocations are done outside of the virtual heap, but are counted against it!

Same result out of memeory, actually it won't matter which method you are using it depend upon the number of bytes you are holding on to read the data that gives out of memory. – PiyushMishra Oct 11 at 12:32.

I did the following to take the image and resize it on the fly. Hope this helps Bitmap bm; bm = Bitmap. CreateScaledBitmap(BitmapFactory.

DecodeFile(filepath),100, 100, true); mPicture = new ImageView(context); mPicture. SetImageBitmap(bm).

4 This approach scales the bitmap. But it doesn't solve the OutOfMemory issue because the full bitmap is being decoded anyway. – Fedor Jan 5 '10 at 6:51 I will see if I can look at my old code, but I think it did solve my out of memory issues.

Will double check my old code. – Chrispix Sep 22 '10 at 17:19.

There are two issues here.... Bitmap memory isn't in the VM heap but rather in the native heap - see BitmapFactory OOM driving me nuts Garbage collection for the native heap is lazier than the VM heap - so you need to be quite aggressive about doing bitmap. Recycle and bitmap =null every time you go through an Activity's onPause or onDestroy.

Its a known bug (code.google.com/p/android/issues/detail?...), its not because of large files. Since Android Caches the Drawables, its going out of memory after using few images. But I found alternate way for it, by skipping the android default cache system.

Soultion: Move the images to "assets" folder and use the following function to get BitmapDrawable public static Drawable 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 new BitmapDrawable(bitmap); }.

Use this bitmap.recylce(); Its solve the problem 100%. Without any image quality issue. Thanks Regards, Arsalan Ansari.

1 It helps but not 100% buddy. – Mayu Mayooresan Sep 23 at 8:32 According to the API, calling recycle() is not needed. – Artem Russakovskii Sep 28 at 1:01 no not at all 100% say 10% – Jawad Amjad Nov 11 at 9:54.

None of the answers above worked for me, but I did come up with a horribly ugly workaround that solved the problem. I added a very small, 1x1 pixel image to my project as a resource, and loaded it into my ImageView before calling into garbage collection. I think it might be that the ImageView was not releasing the Bitmap, so GC never picked it up.It's ugly, but it seems to be working for now.

If (bitmap! = null) { bitmap.recycle(); bitmap = null; } if (imageView! = null) { imageView.

SetImageResource(R.drawable. Tiny); // This is my 1x1 png. } System.gc(); imageView.

SetImageBitmap(...); // Do whatever you need to do to load the image you want.

I have resolved the same issue in the following manner. Bitmap be = null; Drawable d; ImageView I = new ImageView(mContext); try { be = Bitmap. CreateBitmap(320,424,Bitmap.Config.

RGB_565); b. EraseColor(0xFFFFFFFF); Rect r = new Rect(0, 0,320 , 424); Canvas c = new Canvas(b); Paint p = new Paint(); p. SetColor(0xFFC0C0C0); c.

DrawRect(r, p); d = mContext.getResources(). GetDrawable(mImageIdsposition); d. SetBounds(r); d.

Draw(c); /* BitmapFactory. Options o2 = new BitmapFactory.Options(); o2. InTempStorage = new byte128*1024; be = BitmapFactory.

DecodeStream(mContext.getResources(). OpenRawResource(mImageIdsposition), null, o2); o2. InSampleSize=16; o2.

InPurgeable = true;*/ } catch (Exception e){} i. SetImageBitmap(b).

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions