Cathal Comerford
Cathal Comerford

Reputation: 1020

Choosing a max bitmap size for memory concerns

In my application I am going to be loading and displaying various images from a server, and there's no limit to how big each one can be. I've already fought my battles with the various issues of Bitmap memory usage in Android that so many people have complained about here, and I've got that much working in that old bitmaps are being released and recycled when I'm done with them. My issue now is the possibility of a single enormous image exceeding the memory allocation all by itself. I've already looked into the various options for downsizing images to conserve memory and get how all that works - my issue is that I would like to preserve image quality as much as possible, so I would like the Bitmap to use as much memory as it can without killing everything.

So, my question is, given that there is such a wide variety of devices with different memory capacities, is there any way to determine a suitable maximum size at runtime in order to balance memory allocation with image quality?

Upvotes: 4

Views: 1224

Answers (1)

Narcís Calvet
Narcís Calvet

Reputation: 7452

I found myself with similar issues. After some research and testing I came up with a number of methods that helped me on that subject. Those are implemented with C# using Mono for Android but I guess they should be almost identical with Java:

/// <summary>
///Calculates the memory bytes used by the given Bitmap.
/// </summary>
public static long GetBitmapSize(Android.Graphics.Bitmap bmp)
{
  return GetBitmapSize(bmp.Width, bmp.Height, bmp.GetConfig());
}

/// <summary>
///Calculates the memory bytes used by a Bitmap with the given specification.
/// </summary>
public static long GetBitmapSize(long bmpwidth, long bmpheight, Android.Graphics.Bitmap.Config config)
{
  int BytesxPixel = (config == Android.Graphics.Bitmap.Config.Rgb565) ? 2 : 4;

  return bmpwidth * bmpheight * BytesxPixel;
}

/// <summary>
///Calculates the memory available in Android's VM.
/// </summary>
public static long FreeMemory()
{
  return Java.Lang.Runtime.GetRuntime().MaxMemory() - Android.OS.Debug.NativeHeapAllocatedSize;
}

/// <summary>
///Checks if Android's VM has enough memory for a Bitmap with the given specification.
/// </summary>
public static bool CheckBitmapFitsInMemory(long bmpwidth, long bmpheight, Android.Graphics.Bitmap.Config config)
{
  return (GetBitmapSize(bmpwidth, bmpheight, config) < FreeMemory());
}

That code proved pretty reliable preventing out of memory exceptions. An example using those methods in the namespace called Utils is the code snippet below. This code calculates the memory necessary for 3 bitmaps, two of them being 3 times as big as the first one.

/// <summary>
/// Checks if there's enough memory in the VM for managing required bitmaps.
/// </summary>
private bool NotEnoughMemory()
{
  long bytes1 = Utils.GetBitmapSize(this.Width, this.Height, BitmapConfig);
  long bytes2 = Utils.GetBitmapSize(this.Width * 3, this.Height * 3, BitmapConfig);

  return ((bytes1 + bytes2 + bytes2) >= Utils.FreeMemory());
}

Upvotes: 4

Related Questions