I am implementing an application in which an activity shows a image view with full screen. Now i have some images downloaded in application's file directory. I want to set image to image view in that activity for which i am scaling down the larger images. I am getting OutOfMemory error after 10 to 15 mins of using application. error is in decodeFile of BitmapFactory. Here is my code :
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) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)reqHeight);
} else {
inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromFile(String imagePath,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(imagePath, options);
}
Right now i am giving reqHeight = 500 and reqWidth = 500
This code is given in Android guidelines page. Is there anything i am missing, if so please help me out. I tried lots of things but not getting any solution.
Change you int inSampleSize = 1; to int inSampleSize = 2 or 3 and test the application again, I hope this will solve your problem. I also suggest insted of this technique,try lazy loading for all you image dowanload by doing so there will be no bitmap and outOfMemoryError. Yo can have lazy loading - https://github.com/thest1/LazyList
Try using this
Bitmap resizedbitmap2 = Bitmap.createScaledBitmap(your_bitmap, width, height,
true);
it will help you.
There might be a memory leak in your app if you are storing list of bitmaps returned by decodeSampledBitmapFromFile somewhere. Try to check for memory leak and also use Bitmap.recycle() to recycle bitmaps and help android free memory.
Related
I know, there are a lot of similar questions in Stackoverflow. But I could not solve my problem.
I have some kind of jigsaw puzzle. The pictures in the Drawable-nodpi folder are 2500x1250.
I am trying to resize the images with the following code suggested:
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) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
I call it like this:
(I call these codes several times.)
private Bitmap resizeImg (int rsm) {
Bitmap bmp = decodeSampledBitmapFromResource(getResources(),rsm,wdth,hght);
return bmp;
}
I need to use Matrix as the scaling of Imageview. But it's not the size I want. It works right without the Matrix.
I'm solving the Matrix problem like this:
Bitmap.createScaledBitmap
private Bitmap resizeImg (int rsm) {
Bitmap bmp = decodeSampledBitmapFromResource(getResources(),rsm,wdth,hght);
// return bmp;
Bitmap resized = Bitmap.createScaledBitmap(bmp, wdth,hght,true); //I get OutOfMemoryError this line.
return resized;
}
This insertion really solves my problem. But every day I get lots of OutOfMemoryError errors.
What do I need to do to fix this error? Please help me. Thank you.
1] Add largeHeap as true in android manifest to your application tag:
android:largeHeap="true"
2] Recycle your all used bitmaps,
Example:
bmp.recycle();
resized.recycle();
Steps my application performs:-
Download a large no of images and save them on the SDCard.
Load every image into Bitmap and resize them, after resizing replace this resized image with the original one.
My code:-
Bitmap myimage = loadimage(path+temppos+".jpg");
Bitmap finalimage = getResizedBitmap(myimage,width,height);
//save image
.....
//recyclebitmap
myimage.recycle();
finalimage.recycle();
loadimage:-
public Bitmap loadimage(String path)
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inDither=true;
options.inPurgeable=true;
options.inInputShareable=true;
return BitmapFactory.decodeFile(path, options);
}
Now I' populating these images on gridview.
Output(Before):-
Output (After):-
Where Before corresponds to initially when only a few images are downloaded.
And After corresponds to after all the images are downloaded.
Now, I think it is happening maybe because of Bitmap.recycle() method but don't know the reason. Please correct me if I am wrong and point out the error here.
Edit: I must add the grid view shows around 50 downloaded images, but only the first three images are becoming unrecognizable.
Thanks.
For getting your resized Bitmap you can use the below code: (taken from this tutorial)
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;
}
You can also take a look at the official site for getting a hint on loading Bitmaps
Edit
Try to change bitmap configuration to ARGB_8888 for best quality
because RGB_565 configuration can produce slight visual artifacts depending on the configuration of the source (taken from docs)
Update
I think you can take a look at this answer , I think this would solve your problem
I want to download photos from your disk. I used to have a bug OutOfMemory. I coped with this error, but now on some phones I get the error "Bitmap too large to be uploaded into a texture (1840x3264, max = 2048x2048)". In this case, when the picture is uploaded my app begins to slow, jerky, slow down. Please tell me how to upload pictures from the disk so as to avoid these mistakes and express
use this method to create your bitmap-
Bitmap bm=decodeSampledBitmapFromPath(src, reqWidth, reqHeight);
// might be your Screen Height and Width in your Case
use this Defination-
public 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 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;
}
Note- Make Your reqWidth and reqHeight according to your sceenSize.
You can't increase the heap size dynamically.
you can request to use more by using
android:largeHeap="true"
in the manifest.
also, you can use native memory (NDK & JNI) , so you actually bypass the heap size limitation.
here are some posts made about it:
How to cache bitmaps into native memory
JNI bitmap operations , for helping to avoid OOM when using large images
and here's a library made for it:
https://github.com/AndroidDeveloperLB/AndroidJniBitmapOperations
happy coding
regards maven
I have a list in my application that contains all the installed applications with their icons, I'm able to render the installed applications and the icons as well but it is consuming lot of memory as it loads the drawables(icons) of the installed applications into memory as well.
I want to scale down the icon and then load into memory just to reduce the memory usage of the application. Can anyone tell me how that can be achieved.
Note : if PNG format then it will not compress your image because PNG is a lossless format.
and applications icons are in PNG format
Any way to reduce the memory allocation for the icons??
Yeah it's all in the docs:
http://developer.android.com/training/displaying-bitmaps/index.html
Calculate your sample size, i.e. size of the bitmap you want:
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;
}
The decode your bitmap at this size:
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);
}
This should all be done off the UI thread:
http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
You can then cache the bitmaps so you don't have to do it more times than necessary:
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
Use inSampleSize from BitmapFactory.Options
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2; //Downsample 10x
I am using some static images in my application and the images is being kept in the drawable folder.The size of the images are near about 2 MB but I have scaled them properly but still it is showing out of memory error due to the bitmap size during run time.And this is specially for samsung galaxy s3.
Can anybody plz tell me how to stop this and to reduce the bitmap size.
I have tried using this code for recycling images:
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 = 8;
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;
}
First compress the images to check if actually these are the ones that leak memory.
Get used to using tools to measure memory you are using and finding leaks because simply this is a way to do it.
You might start here:
What Android tools and methods work best to find memory/resource leaks?
I also recomend this code for image viewing
https://github.com/nostra13/Android-Universal-Image-Loader