I want to load an image on android
background = BitmapFactory.decodeResource(getResources(),R.drawable.hangmanbegin);
background = Bitmap.createScaledBitmap(background,screenx,screeny,false);
The image is 800*1280 pixels , so if I'm correct it should use arround 3MB of memory space?
But my heap grows from 15MB to 29MB just at that phase , so no window or context leaking?
How is this explained? en what can you do about it?
Thnx in advance!
Bitmaps take up a lot of memory, especially for rich images like
photographs. For example, the camera on the Galaxy Nexus takes photos
up to 2592x1936 pixels (5 megapixels). If the bitmap configuration
used is ARGB_8888 (the default from the Android 2.3 onward) then
loading this image into memory takes about 19MB of memory (2592*1936*4
bytes), immediately exhausting the per-app limit on some devices.
from http://developer.android.com/training/displaying-bitmaps/index.html
credit and below it a way to approach a fix https://stackoverflow.com/a/10127787/643500
Related
I want to load images with big size, but i have problem to make it. it Crashes, because OutOfMemoryError. here is my array :
Integer[] img = {
R.drawble.pic1, R.drawble.pic2, R.drawble.pic3, R.drawble.pic4
};
how to convert img[0],img[1],img[2] and img[3] to bitmap?
Please help.. Sorry my bad english.
Try this code, you'll convert an array of ids into an array of Bitmap:
Integer[] img = { R.drawble.pic1, R.drawble.pic2, R.drawble.pic3,
R.drawble.pic4 };
Bitmap[] bitmap = new Bitmap[img.length];
for (int i = 0; i < img.length; i++)
bitmap[i] = BitmapFactory.decodeResource(getResources(), img[i]);
If you have problems to convert big size image take a look at Displaying Bitmaps Efficiently.
Check here: http://developer.android.com/training/building-graphics.html
and the class BitmapFactory: http://developer.android.com/reference/android/graphics/BitmapFactory.html
Android apps have a limited heap size (minimum on old devices is as little as 16MB). This varies per device, so be careful during QA. Since a bitmap can take as much as 4 bytes per pixel, large bitmaps can easily fill up your heap (1000 x 1000 pixels = 3.8MB)
What this means is that you have to be very careful and use several tactics to avoid wasting memory:
Don't load all the bitmaps at the same time to memory. If you're showing them for example in a ViewPager you can load only 1-2 pages at a time. When a page is hidden, destroy its bitmap and call bitmap.recycle() to make sure the memory is freed immediately.
If the bitmap is larger than your screen size, you can scale it down to save memory. The technique here will let you load it initially reduced by 2/3/4.. If you need more fine-tuning, you can load it full size and then rescale using Bitmap.createScaledBitmap. Just don't forget to recycle() the original large bitmap immediately.
Make sure to explore your app's memory usage by using memory inspection tools such as DDMS or Eclipse MAT. I recommend to do most explorations on Android 4+ since 2.x saved bitmaps in the native heap which can't be explored easily. If you can keep your app under 16MB peak memory consumption, you should never hit an OutOfMemoryError again.
I'm developing an Android app that has to display some pictures (usually taken by the phone's camera) on the screen. The way that I've created a bitmap is:
Uri uri = Uri.withAppendedPath(Images.Media.EXTERNAL_CONTENT_URI, "" + mediaId);
bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri));
The 2nd line of this ends up on some handsets with OutOfMemoryException. Am I doing something wrong or maybe is there any alternative way of doing the same?
Thanks in advance for any ideas
The photos from the camera are several MBs large. Android applications have a maximum of 24MB RAM available (see What is the maximum memory limits per application for Android 2.2?)
So if your application has several images from the camera, it won't fit in the RAM available to your application.
Scaling down your image(s) is the only solution I am afraid...
I'm trying to load a background image for a game as well as some smaller images, placing them on a Canvas, and letting people interact with the smaller overlayed images (like move, rotate)
In order to maintain aspect ratio (e.g. 5:3) I tried loading in the images as a bitmap and resizing them myself. The idea was to do cropping/letter-boxing for the background according to the canvas's width/height, and maintain the correct ratio of size for the smaller images.
Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), resourceImg);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg2, 0, 0, width, height, matrix, true);
In order to cater for tablets/phones i have a background PNG background image at 1600x1000 and 200kb.
However I am now struggling with out of memory issues due to the bitmap being 1600x1000x4byte=6.4 mb of ram and more when it tries to resize.
(I am using the emulator at the moment when these issues occur)
I decided to change it to use canvas.setBackgroundResource
SceneCanvas sceneCanvas = (SceneCanvas) findViewById(R.id.the_canvas);
sceneCanvas.setBackgroundResource(R.drawable.my_scene_1600x900);
This works well, except it fills the screen and does not maintain aspect ratio.
Is there a way to set the background maintaining aspect ratio? Or have I just gone down the wrong route completely and should use ImageViews and render to the canvas somehow to avoid OutOfMemory issues
Given that Java code is only allowed a heap size of around 20MB or so, you’re always going to have trouble with large bitmaps (unless you resort to native code in C/C++/etc).
One option is to use a BitmapFactory to load your image, and in the Options you can specify an inSampleSize to downsample the image as it’s being read in. This should avoid chewing up memory by trying to load the entire original image. There is even an inJustDecodeBounds option, so your code can check the dimensions of the image, instead of having them hard-wired into the code.
It seems that the memory limit on Android is somewhere between 16 - 24 MB memory (depending on device). This is regardless of whether the device has a lot more memory. Also, the memory used by Bitmaps is included in the limit, resulting in lang.OutOfMemoryError: bitmap size exceeds VM budget. After some searching, there are 3 options I could find:
Allocate memory from native code using the NDK (native development kit) and JNI
For images one can also use OpenGL textures, the texture memory is not counted towards the limit.
take advantage of certain bitmap options to reduce size; http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html
To see how much memory your app has allocated one can use, android.os.Debug.getNativeHeapAllocatedSize().
I am developing a game on android.Like tower defense.
I am using surface view.I am using some image as bitmap.(Spritesheets, tilesets, buttons, backgrounds,efects vs.)
Now images are nearly 5-6 mb.And i get this error when i run my game:
Bitmap size exceeds VM budget
19464192-byte external allocation too large for this process.
I call images like that
BitmapFactory.decodeResource(res, id)
and i put it to array.
I can't scale images.I am using all of them.
I tried that
options.inPurgeable=true;
and it work but the image is loading very slowly.I load a spritesheet with that and when it is loading, i get very very low fps.
What can I do?
I've had this problem too; there's really no solution other than to reduce the number/size of bitmaps that you have loaded at once. Some older Android devices only allocate 16MB to the heap for your whole application, and bitmaps are stored in memory uncompressed once you load them, so it's not hard to exceed 16MB with large backgrounds, etc. (An 854x480, 32-bit bitmap is about 1.6MB uncompressed.)
In my game I was able to get around it by only loading bitmaps that I was going to use in the current level (e.g. I have a single Bitmap object for the background that gets reloaded from resources each time it changes, rather than maintaining multiple Bitmaps in memory. I just maintain an int that tracks which resource I have loaded currently.)
Your sprite sheet is huge, so I think you're right that you'll need to reduce the size of your animations. Alternatively, loading from resources is decently fast, so you might be able to get away with doing something like only loading the animation strip for the character's current direction, and have him pause slightly when he turns while you replace it with the new animation strip. That might get complicated though.
Also, I highly recommend testing your app on the emulator with a VM heap set to 16mb, to make sure you've fixed the problem for all devices. (The emulator usually defaults to 24mb, so it's easy for that to go untested and generate some 1-star reviews after release.)
I am not a game dev however I would like to think I know Android enough.
Loading images of the size is almost certain to throw errors. Why are the images that file size?
There is an example at http://p-xr.com/android-tutorial-how-to-paint-animate-loop-and-remove-a-sprite/. If you notice he has an explosion sprite of only ~200Kb. Even a more detailed image would not take much more file space.
OK some suggestions:
Are you loading all your spritesheets onto a single sheet or is
each spritesheet in a seperate file? If they are all on one I would
split them up.
Lower the resolution of the images, an Android device is portable
and some only have a low resolution screen. For example the HTC
Wildfire has a resolution of 240x320 (LDPI device) and is quite a
common device. You have not stated the image dimensions so we can't be sure if this is practical.
Finally; I am not a game programmer but I found this tutorial (part of the same series) quite enlightening - http://p-xr.com/android-tutorial-2d-canvas-graphics/. I wonder if you are applying a pattern that is not appropriate for Android, however without code I cannot say.
Right something a little off topic but worth noting...
People under estimate the power of the View. While there is a certain amount of logic to using a SurfaceView, the standard View will do quite a lot on its own. A SurfaceView more often than not requires an underlying thread to run (that you will have to setup yourself) in order to make it work. A View however calls onDraw(), which can be utilized in a variety of ways including the postinvalidate() method (see What does postInvalidate() do?).
In any case it might be worth checking out this tutorial http://mindtherobot.com/blog/272/android-custom-ui-making-a-vintage-thermometer/. Personally, it was an excellent example of a custom View and what you can do with them. I rewrote a few sections and made a pocket watch app.
This is a bit of a followup to my last question: Canvas is drawing too slowly
Now that I can draw images more quickly, the problem I am faced with is that the actual loading of the images takes far too long.
In the app I am working on, the user is able to play back video frames (jpegs) in succession, as though he is viewing the video in realtime. I have been using BitmapFactory.decodeFile() to load each jpeg in a Bitmap. I'm unable to load all images at once since there are about 240 of them, and that would use up all of my heap space. What I have been doing is preloading up to 6 at a time into an array by way of a separate thread in order to cut down on the time it takes for each image to display.
Unfortunately, it takes somewhere between 50 and 90ms to load an image, and I need to show an image every 42ms. Is there a faster way to load images possibly?
For clarification, these images are in a folder on the SD card, and they are all 720x480 jpegs. I am sampling them at half that size to cut down on memory usage.
I ended up doing this quite a bit differently than I had originally envisioned. There was quite a bit to it, but here's the gist of how I achieved my goal:
All images are stored on SD card and written to one file (each image takes up X bytes in the file)
Use native code to read from and write to the image file
When requesting an image, I pass the index of the image in the list and a bitmap object (RGB_565) to the native code using a JNI wrapper
The native code locks the bitmap surface, writes pixel data (as a uint8_t**) directly to the bitmap, then unlocks it
The image is rendered to the screen
By doing it this way, I only needed to store one image in memory at a time, and I was able to bypass garbage collection (since the bitmap was only created once and then repopulated natively). I hope someone else might find this strategy useful.
Guess you already tried all methods in this tutorial http://www.higherpass.com/Android/Tutorials/Working-With-Images-In-Android/2/ and chosen the fastest. Maybe tweaking resizing can decrease loading time.
Best of all would of course be if you didn't have to resize the images at all. If you have full control of the images maybe you could try to pack them as sprites, see article http://www.droidnova.com/2d-sprite-animation-in-android,471.html