0

I would like to display an image as the screen background and since I am having difficulties with image view's scale_type in the xml, I am doing the computations with image ratio and screen dimensions in a function, nothing too complicated

public static Bitmap BitmapToView(Bitmap img, View v) { int imgWidth = img.getWidth(); int imgHeight = img.getHeight(); int bckWidth = v.getWidth(); int bckHeight = v.getHeight(); float ratio1 = (float) bckWidth / imgWidth; float ratio2 = (float) bckHeight / imgHeight; float maxRatio = Math.max(ratio1, ratio2); int newHeight = Math.max((int) (imgHeight * maxRatio), bckHeight); int newWidth = Math.max((int) Math.ceil(imgWidth * maxRatio), bckWidth); Bitmap tmp_image = Bitmap.createScaledBitmap(img, newWidth, newHeight, true); Bitmap ret_image = Bitmap.createBitmap(tmp_image, Math.abs(newWidth - bckWidth)/2, Math.abs(newHeight - bckHeight)/2, bckWidth, bckHeight); tmp_image.recycle(); return ret_image; } Options options = new Options(); options.inJustDecodeBounds = false; Bitmap img = BitmapFactory.decodeFile(imgFilePath, options); Bitmap newImage = BitmapToView(img, findViewById(R.id.myRelativeLayout); // RelariveLayout takes up the whole screen ; failing on Samsung Galaxy S4 findViewById(R.id.myRelativeLayout).setBackground(new BitmapDrawable(newimage)); 

And sometimes I get an out of memory exception I have tried to use .recycle() here and there but then I get "Canvas: trying to use a recycled bitmap"

Any idea ? Thanks

2
  • Remember that OOM doesn't necessarily mean your last request for memory was the problem. It means your entire app is using too much total memory. I'd run hprof to find out where I'm using my memory and look for leaks or objects that are no longer needed. I'd also look into caching bitmaps and reading them in from disk when they fall out of cache. Commented Mar 23, 2014 at 16:14
  • @GabeSechan How come there is no memory exception when you set the drawable in the xml ? Commented Mar 23, 2014 at 16:30

1 Answer 1

1

You said you already tried recycle()? But I see you use the same variable for the scaled and not scaled image, have you tried this:

Bitmap image = BitmapFactory.decodeFile("/.../path", options); ... Bitmap scaledImage = Bitmap.createScaledBitmap(image, newWidth, newHeight, true); image.recycle(); // <-- Use a new variable for the scaled image so you can recycle the not scaled one 

If that doesn't help you please post more of your code and give us more information about what you are trying to do. Otherwise it will be difficult to help you.

EDIT:

This code should crop the small image before scaling it up and should therefore significantly reduce how much memory you use.

Unfortunately I can't test it right now but I'm pretty sure it should work as expected. If there are any problems feel free to ask.

public static Bitmap BitmapToView(Bitmap img, View v) { double imgWidth = img.getWidth(); double imgHeight = img.getHeight(); double viewWidth = v.getWidth(); double viewHeight = v.getHeight(); // Crop image to required aspect ratio double imgRatio = imgWidth / imgHeight; double viewRatio = viewWidth / viewHeight; double cropWidth; double cropHeight; if (imgRatio > viewRatio) { cropWidth = viewRatio * imgHeight; cropHeight = imgHeight; } else { cropHeight = imgWidth / viewRatio; cropWidth = imgWidth; } int cropX = (int) (imgWidth / 2.0 - cropWidth / 2.0); int cropY = (int) (imgHeight / 2.0 - cropHeight / 2.0); Bitmap croppedBitmap = Bitmap.createBitmap(img, cropX, cropY, (int)cropWidth, (int)cropHeight); img.recycle(); // Scale image to fill view Bitmap finalBitmap = Bitmap.createScaledBitmap(croppedBitmap, (int)viewWidth, (int)viewHeight, true); croppedBitmap.recycle(); return finalBitmap; } 
Sign up to request clarification or add additional context in comments.

7 Comments

Super strange, I still get the error and yet the recycle comes after the last use of the temporary bitmap. See edit
I have an image lets say 800x900 and I want to apply it on a screen (1200x1600). so I resize the image and then crop
but this doesn't explain the problem with recycle called after using the image, no ? or is createBitmap something that just uses references (svg style) ?
The problem is that with this algorithm you have two big bitmaps in your memory. What I would suggest is that you turn your algorithm upside down and crop the original image to the required aspect ratio and scale that up to the required size. That should significantly reduce the memory you are consuming. Especially if you properly call recycle() on all not needed bitmaps.
If you post all of your code I can assist you with that.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.