I'm trying to write simple application where I can swipe between photos (like that standard gallery app on each device). Standard one demonstrates impressive performance - it displays next photo instantly while takes only about 15 MB of memory. It seems like it keeps next and previous images in memory so it doesn't have delay due to loading them from sd-card. I think that if the application keeps at least 3 Bitmap objects of such size in memory, it will take much more than 15 MB. So how it works? Don't use Bitmap or what? Thank you.
Remember that the bitmap on the screen might not be the size of your original file.
Take a 720p screen for example, a 4096*3072 picture will be decoded and re-sized to screen size.
Even the APP might be using ARGB8888 format to display a bitmap, the memory size is 1280*720*4 = 3686400 bytes, that is about 3.5M.
And if we use RGB565 format, the size will be half small then.
What's more, not all the picture is 'full screen'.
Related
I am using a button with a png background for CopyToClipboard function in my app (used about 6-7 times in various fragment). Since the image should be small for my purpose, I increased the area of my image by putting in extra transparent area around the image so that I could increase the button size for clickable area but keep the image small (I know its not efficient and since then I have devised better way to achieve this).
I noticed the huge spikes later on afterwards when uploading some other images (big images about 150kb size), and after a lot of debugging (and I do mean a lot!) I found that the problem was not due to the bigger images but due to the CopyToClipboard image which was of just 8kb in size!!! Changing back to older CopyToClipboard image (having lesser Transparent area) brought the memory consumption back to normal.
My question is why did that happen? For such a small image to create such huge spikes (more than doubled the memory consumption from previous) and made the app slow, is quite baffling.
Image shown below : The White area is the transparent area. My button dimension : 15dp x 15dp .
I repeat, My question is why did that happen? Not a solution for it since I already solved the problem.
It doesn't really matter that your image is only 7-8KB on disk, because it will take much more memory when it's decoded.
Apparently, large transparent area can be efficiently encoded in PNG file, so the image has that small size.
But in fact, it's dimension is (600 x 745), so in memory it will take roughly (600 * 745 * 4) bytes, plus some meta information, so nearly 2 megabytes. 4 multiplier stands for an amount of bytes needed to encode color with alpha channel.
Android Bitmaps are represented internally by linear one-dimensional array of integers, so you can imagine that system needs to allocate an array with size 600 * 745 = 447000 to create your Bitmap.
That's why memory consumption is so high for such a simple image.
I'm taking whole screenshot of a WebView and display the bitmap on an ImageView. The bitmap can be 7 screen height. (E.g. 1440x14000 px)
I'm frequently face with
OutOfMemoryError.
I've seen this
This says that load a scaled down version into memory but I don't want to lose image quality. There are the same approaches on the web.
Is there any way to handle OutOfMemoryError without loading scaled down version?
The bitmap can be 7 screen height. (E.g. 1440x14000 px)
Note that this means that the user cannot see the whole image at once at full resolution.
I'm frequently face with OutOfMemoryError
On most devices, you will have a very difficult time loading an image that large, as you cannot get a single contiguous memory block that big.
This says that load a scaled down version into memory but I don't want to lose image quality
To some extent, you do not have much of a choice. If you want the user to see the full extent of the picture at once, the image has to be scaled to fit the screen.
Is there any way to handle OutOfMemoryError without loading scaled down version?
There are ImageView replacements that offer pan and zoom. Some of those, such as this one, handle loading in pieces of the image at a time, with whatever scaling is necessary for the current zoom level, to make it more likely that you will be able to show the user the entire image.
It is not a solution, of course, but I'm also not familiar with your exact needs, so maybe this may help you a little - you can try to play with bitmap options during decoding. Try to use Bitmap.Config.inPreferredConfig as RGB_565 - this will reduce size of your bitmap twice comparing to default ARGB_8888. But, of course, if you use complex images in your web page this may reduce their quality.
Whenever I try to show large size(1 MB) bitmap in imageview, system throw OutOfMemory exception.
If I place 7-8 MB image, gallery can easily show that image.
Just want to know How device default gallery is able to show large image in easy way?
Which mechanism is used by device gallery?
Generally speaking, they subsample the image. A 1MB PNG or JPEG file will be much higher resolution than the screen, and so it is wasteful to load the whole image in. Subsampling allows you to load the image in much closer to the actual size of the ImageView you will use, allowing it to fit in memory better. A simple approach to subsampling involves using inSampleSize on BitmapFactory.Options; Dave Morrissey's SubsamplingScaleImageView offers pinch-to-zoom and such while peforming subsampling (note: I have not tried this component, as I just ran across it a minute ago).
I use a skin in my app,and load something like 1.5 Mb of images at some of the activities.
This shouldn't be a problem.... 1.5 Mb + default of ~6Mb for the app when loaded... however, things are quite different.
each png I load as a drawable in my layout xmls, is being multiplied by at least 10 from its actual size...., I wrote a sample app with nothing except for a black screen, and loaded it once without anything on it and got native-heap of 5.8Mb, and then loaded it with a small png of 25Kb and guess what.... 6.25Mb.
I loaded my application with nothing but the skin, and it started with 14.5Mb!!!!!!!!
so now I am in the middle of doing a bitmap recycle operation after each and every activity change.
Is this a known issue with android?
png files are loaded with much bigger size inside the native-heap?
is there a solution other than my current plan?
Thanks.
PNG files (as well as many other image formats, such as JPEG) are compressed files, pretty much similar to zip-files. When you load them into memory they will be uncompressed
and take more space consequently.
How much depends on the internal image config, the default is ARGB8888, which takes 4 bytes per pixel. So the memory consumption only depends on the image size, not on the filesize on disk (which can get pretty small. For example: A 500x500 px bitmap consisting of one color has a good compression ratio).
Example for a 500x500 px image is 500*500*4 bytes = 0.954 MB, which is almost one megabyte.
I know there is a lot of discussion about android bitmap images out of memory but I was wondering if someone could explain it to me..
Currently in my app I have an activity which lists image thumbnail (low quality) and when I click an image it opens a new activity to view the image full screen. In my 2nd activity class I have:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
bm = BitmapFactory.decodeFile(myImagePath, options);
I then put this into an ImageView to display it. This works and displays my image to its full quality. However if i click back and then click to see that image again (and repeat this 6 times) .. on the 6th time opening the image (activity2) I get an out of memory error saying Heap size=6919KB, Allocated=3125KB, Bitmap Size = 25848KB!
How is bitmap size that big? I assumed it may be creating new instances all the time so I then decided to put a method in my 2nd activity for when the back key is pressed..and in this method I set my bitmap=null and also did System.gc() to clear the garbage collector BUT this did not fix the problem. I still get an out of memory error on the 6th time of clicking on the thumbnail to view the image in full resolution
Can anyone explain why? Thanks
There is some great information from android that explains it all in detail, and how to overcome this problem here.
Each pixel is 4 Bytes. 6M Pixel = 24MBs
One photo can use up all the Memory.
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.
Again I point you to this great link I found from another SO Question that has tutorials of how to properly over come the problem.
inSample size should be set so that the image is scaled to the size of the display area (1 = full size) unless there is some reason you think you need all the bits of the image, so 2 would = 1/2 scale 4 1/4 scale etc.
Also try bm.recycle() when you are finished with the bitmap before using =null
Update
Look at the second answer what does recycle do unless you have already tried that and it didn't work. I have done similar things with loading images and never run out of memory, that's not proof that it will work for you, but it's a best practice as far as I can tell.