Out Of Memory Exception during decode image from imagepath
Today In this tutorial we are sharing the code and knowledge about the out of memory exception when we are loading the image on imageview in the listview.
Images come in all shapes and sizes. In many cases they are larger than required for a typical application user interface (UI). For example, the system Gallery application displays photos taken using your Android devices's camera which are typically much higher resolution than the screen density of your device.
Given that you are working with limited memory, ideally you only want to load a lower resolution version in memory. The lower resolution version should match the size of the UI component that displays it. An image with a higher resolution does not provide any visible benefit, but still takes up precious memory and incurs additional performance overhead due to additional on the fly scaling.
Most of the time when we are taking the picture from the Camera or from the Gallery the image is too large. In that case when we are going to decode the image from the image path then it throw the out of memory exception just because of the when decoding the image that time it store in heap of memory. That contain the small size for executing this process. That's why it give the out of memory exception.
So the solution is: we need to decode the via FileOutPutStream or make it first re size the image after we can decode. Both are working perfect in my side. But when we showing the image in list view and we are not resizing the image then our listview working very slow just because of the large image size. So we need to scale the image first.
Here I am giving the three option to decode the image from the image path.
It gives the most of the time out of memory exception when image size is large. So we need to use Bitmap Option for the same.
But this is not a good solution for the decode the image. Some time it also gives the Out Of Memory Exception . So let comes in the second way.
It does not give the Exception, we can use this to show the image on a particular imageview.
But It have certain limitation, After the decode we can not make the scale of this bitmap. And Its size will be same as a large so it makes slow to show in the list veiw.
So lets come the third way to decode the image from the image path. This one is the best and optamized solution which have seen the above.
If you want to make a small image from large image with height and width like 60 and 60 and scroll the listview fast then use this concept
If you want to decode the image from the Drawable or the Resources then use this way.
Images come in all shapes and sizes. In many cases they are larger than required for a typical application user interface (UI). For example, the system Gallery application displays photos taken using your Android devices's camera which are typically much higher resolution than the screen density of your device.
Given that you are working with limited memory, ideally you only want to load a lower resolution version in memory. The lower resolution version should match the size of the UI component that displays it. An image with a higher resolution does not provide any visible benefit, but still takes up precious memory and incurs additional performance overhead due to additional on the fly scaling.
Most of the time when we are taking the picture from the Camera or from the Gallery the image is too large. In that case when we are going to decode the image from the image path then it throw the out of memory exception just because of the when decoding the image that time it store in heap of memory. That contain the small size for executing this process. That's why it give the out of memory exception.
So the solution is: we need to decode the via FileOutPutStream or make it first re size the image after we can decode. Both are working perfect in my side. But when we showing the image in list view and we are not resizing the image then our listview working very slow just because of the large image size. So we need to scale the image first.
Here I am giving the three option to decode the image from the image path.
1. When decode the image via normal way.
1
2
| String imageInSD = "/sdcard/UserImages/" + userImageName; Bitmap bitmap = BitmapFactory.decodeFile(imageInSD); |
It gives the most of the time out of memory exception when image size is large. So we need to use Bitmap Option for the same.
1
2
3
4
5
| String imageInSD = "/sdcard/UserImages/" + userImageName; BitmapFactory.Options options= null ; options = new BitmapFactory.Options(); options.inSampleSize = 2; Bitmap bitmap = BitmapFactory.decodeFile(imageInSD, null , options); |
But this is not a good solution for the decode the image. Some time it also gives the Out Of Memory Exception . So let comes in the second way.
2. Decode the Image from the image path via FileInputStream and FileOutputStream.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| public static Bitmap convertBitmap(String path) { Bitmap bitmap= null ; 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 byte[32 * 1024]; File file= new File(path); FileInputStream fs= null ; try { fs = new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } try { if (fs!= null ) { bitmap=BitmapFactory.decodeFileDescriptor(fs.getFD(), null , bfOptions); } } catch (IOException e) { e.printStackTrace(); } finally{ if (fs!= null ) { try { fs.close(); } catch (IOException e) { e.printStackTrace(); } } } return bitmap; } |
It does not give the Exception, we can use this to show the image on a particular imageview.
But It have certain limitation, After the decode we can not make the scale of this bitmap. And Its size will be same as a large so it makes slow to show in the list veiw.
So lets come the third way to decode the image from the image path. This one is the best and optamized solution which have seen the above.
If you want to make a small image from large image with height and width like 60 and 60 and scroll the listview fast then use this concept
3. First Resize the Image Size and then after Decode the Image From Image Path.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| public static Bitmap decodeSampledBitmapFromPath(String path, int reqWidth, int reqHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true ; BitmapFactory.decodeFile(path, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false ; Bitmap bmp = BitmapFactory.decodeFile(path, options); return bmp; } public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { if (width > height) { inSampleSize = Math.round((float) height / (float) reqHeight); } else { inSampleSize = Math.round((float) width / (float) reqWidth); } } return inSampleSize; } |
If you want to decode the image from the Drawable or the Resources then use this way.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true ; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false ; return BitmapFactory.decodeResource(res, resId, options); } public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { // Calculate ratios of height and width to requested height and width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // Choose the smallest ratio as inSampleSize value, this will guarantee // a final image with both dimensions larger than or equal to the // requested height and width. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; }
|
Comments
Post a Comment