Getting OOM big time in my game UI (I'm only targeting kitkat and above)
I noticed that if I use a android:src="#drawable/empty_screen_game_setup" in XML, leaving and entering the activity always has the same memory usage.
If I DON'T set src in XML, but rather use the following google code, leaving and entering the activity makes the memory usage climb like crazy. This is a test app with no other code because I'm trying to understand the OOM. So much conflicting info out there!!
Is it better to just use src in XML memory-wise? I was hoping to use one set of ressources in no-dpi and scale them to size with bitmapfactory given the screen size but I guess that's not best :(
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;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
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);
}
And in onCreate:
glass = (ImageView) findViewById(R.id.imageViewGlass);
glass.setImageBitmap( decodeSampledBitmapFromResource(getResources(), R.drawable.empty_screen_game_setup, 500, 300) );
Related
I have one image which have color code of #AAA28B (170R,162G,139B). Now let's say current image size is 1200x1200 now I want to make it scale down at 600x600 so i use below code and get resulted in bitmap but the problem is its bitmap color code change to #ABA38C, So it RGB values increase to plus one compare to original image color and become (171R,163G,140B) how to prevent this?.
See attach a screenshot where the first image if original loaded directly from android drawable and other it loads by using following code.
private void loadImage(int width, int height){
Bitmap bitMapTest=BitmapFactory.decodeResource(getResources(),R.drawable.ic_test);
Log.i("IMAGE","Image format is"+ bitMapTest.getConfig().name()+
"Image size is"+ bitMapTest.hasAlpha() + "bitmap size is"+ bitMapTest.getHeight());
Bitmap decodeBitmap=decodeSampledBitmapFromResource(getResources(),R.drawable.ic_test,width,height);
Log.i("IMAGE","Image format is"+ decodeBitmap.getConfig().name()+
"Image size is"+ decodeBitmap.hasAlpha() + "bitmap size is"+ decodeBitmap.getHeight());
//adjust of alha deos not give me any help result remain same
//decodeBitmap=adjustOpacity(decodeBitmap);
mImgView.setImageBitmap(decodeBitmap);
}
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;
options.inPreferredConfig= Bitmap.Config.ARGB_8888;
options.inScaled=false;
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 = 2;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
Here is orginal image :-
It seems like applying following code for scaledown working fine for the solid image like this.
Bitmap decodeBitmap=Bitmap.createScaledBitmap(sourceBitmap,width,height,false/*Make sure filter is false*/);
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();
I have an problem. I don't get any idea, how to decode image into bitmap from below json response.
response: [{"namae":"example",
photo:[125,122,10,22,34,5,5,56,5,0,0,..........................,23]}]
I don't know how to get bitmap image from value of photo parameter.
Thanks in advance.
Use decodeByteArray() from BitmapFactory class
Get the bytes from the json, lets call it
bytes photoBytes=array.getJSONArray(0);
Do this:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(photoBytes,0,photoBytes.length,options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, <preferredWidth>, <preferredHeight>);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap bmp1=BitmapFactory.decodeByteArray(photoBytes,0,photoBytes.length,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;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;}
check google site for more info
I have a set of image files stored in internal storage, each file size is about 750 KB. I need to create a 360 degrees animation like with this images, so, I load each image in a list, while I'm doing this process an out of memory exception appears.
I have been reading about bitmap processing on Android, but in this case is not about resize bitmap dimensions, the dimensions are OK (600, 450) because its a tablet application, is about image quality I think.
Is there a way to reduce the memory each bitmap takes?.
It is not possible without reducing image dimensions.
All images with the same dimensions require same amount of RAM, regardless it size on disk and compression. Graphics adapter don't understand different image types and compression and it needs only uncompressed raw array of pixels. And it size is constant
For example
size = width * height * 4; // for RGBA_8888
size = width * height * 2; // for RGB_565
So you should reduce image dimensions or use caching on the disk and remove bitmaps from the RAM that are currently invisible and reload from disk when needed.
There is a great resource on how to do this here:
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
Basically you need to load a bitmap at a different resolution using these two functions:
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;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
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);
}
Then set the image as follows:
imageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(),
R.drawable.my_image_resource,
imageView.getWidth(),
imageView.getHeight()));
Hope that helps!
I have images more than 6000px height. Whenever I tried to display these images I got out of memory exception.
I have seen many links but none of matches my need. Because mostly people suggesting image re-sizing solution. But If I'll re-size my image than I am unable to read the text in images due to poor quality.
I want some help in creating some code that can open an image without re-sizing it also with zooming effect.
Any help would be really appreciated.
Try to use google recommendation for this problem.
For avoid OOM you need to implement this block of 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) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
Try using a WebView to show the image, instead of ImageView
I would suggest you "cut" this image in 3 smaller ones and then load them as three images: the first one will be at y:0 and be height 2000px, the second one y:2000px and height 2000px and the third one at y: 4000px.
Do you think this could work?
Good luck
try this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullscreen_view);
imageView = (ImageView) findViewById(R.id.full_image_view);
imageView.setImageBitmap(decodeSampledBitmapFromResource(imgpath));
}
//Load a bitmap from a resource with a target size
Bitmap decodeSampledBitmapFromResource(String res) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(res, options);
//Calculate display dimention for maximum reqwidth and reqheigth
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int xDim = size.x;
int yDim = size.y;
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, xDim, yDim);
// Decode bitmap with inSampleSize se5t
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(res, options);
}
int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
int inSampleSize = 1; //Default subsampling size
// Calculate the largest inSampleSize value
while ((options.outHeight / inSampleSize) > reqHeight
|| (options.outWidth / inSampleSize) > reqWidth) {
inSampleSize += 1;
}
return inSampleSize;
}
In Application manifest file tag set largeHeap true
<application
android:largeHeap="true"
Also Use Picasso or Glide to load image in ImageView