There are different sources from which we can load the images into android application. Sometimes the image size is vary based on the source of the images. The primary source of image in mobile phone is camera and each mobile phone has different camera specification.
So as per camera specification we would get images with different resolution and size. As each mobile phone has come up with limited availability of memory, we must handle memory efficiently.
Overview :
Let’s consider that we have one android application which provides the feature to take images from camera as well as from gallery and store into database for further processing and displays in application. In many cases due to higher resolution of camera images are also captured with higher resolution which can be larger than required for our application user interface component.
If we have small size of UI component (Thumbnail) that going to display captured image, than higher resolution images does not give any additional benefits in terms of visibility to our application, but it will consume significant amount of memory and reduce the performance of the application. Sometimes loading large images leads to “Out of Memory” errors in our crash reports. Android has a limited memory and we must handle it efficiently for better and crash free application performance.
Problem Statement
When we load images from various sources to UI component of android application, we need to decode the image into Bitmap. When user capture images using camera it will store in compressed format into internal or external memory (Disk), but when you try to decode the image into bitmap it will load image into memory (RAM) and it is no longer into compressed format and takes more memory as necessary for each pixels. This will lead to “Out of memory” error when required memory exceeds then available memory.
We can check amount for memory consumed by bitmap using bitmap.getByteCount() method.
Solution
Step 1: Read Bitmap Size
We will first be going to read height and width for bitmap. There are different ways to decode the image to create bitmap. So, we must choose appropriate decoding method based on source of the image. The BitmapFactory class provides several decoding methods as follows decodeByteArray(), decodeFile(), decodeResource() etc.
While reading the dimensions of the image we need to understand we should not load image into memory as we only want to know the dimensions of the image. To do so we need to configure BitmapFactory.Options class and set inJustDecodeBounds flag as true.
Setting inJustDecodeBounds flag to true while decoding the images will avoid memory allocation and image will not load into memory and it will return height and width of image and bitmap as null. This method helps you to calculate height and width of image prior to load image into memory and construct bitmap.
Step 2: Reduce the Bitmap Size
Now as we know the dimensions of the image, we can decide whether to load full image into memory or subsampled version of image into memory. This decision is based on size of image and the size of UI component in which we will going to show this image.
For example:
If our image size is 3120×4160 and we will be going to show this image into small 312×416 thumbnail in an ImageView then it is not worth to load such large image into memory.
To reduce the size of image we can use inSampleSize option which is belong to BitmapFactory.Options class. inSampleSize is nothing but scaling factor that we can specify while decoding image to bitmap.
For example:
If we have an image 3120×4160 and we set inSampleSize 2 before decoding, then we will have 1560×2080 image after decoding operation. 1560×2080 is still large than ImageView dimensions. Sometimes we can have image with size 200×600 and if we apply inSampleSize as 2 then we will get decoded bitmap with size 100×300 which smaller than ImageView size and these dimensions of image might give us blur image. So, we cannot set inSampleSize to specific number we have to decide it run time according to size of image.
In android documentation, they calculate it power of two based, but we can write our own algorithm according to requirement. You can refer android documentation to get the code of inSampleSize calculation based on image size.
Once we get appropriate inSampleSize we must have to set inJustDecodeBounds flag to false and set these properties in BitmapFactory.Options class. At the end we will pass object of BitmapFactory.Options class to appropriate decoding method.
To know amount of memory now reduced, we can use bitmap.getByteCount() method.
References
https://developer.android.com/topic/performance/graphics/load-bitmap.html
Join our mailing list to receive updates from our team