Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

catch "RuntimeException: Canvas: trying to draw too large..."

I have an application which draws an image from the file system to screen like so:

Bitmap image = BitmapFactory.decodeFile(file.getPath());
imageView.setImageBitmap(image);

If the image is very large I see this error:

java.lang.RuntimeException: Canvas: trying to draw too large(213828900bytes) bitmap.
    at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:260)
    at android.graphics.Canvas.drawBitmap(Canvas.java:1415)
    ...

The stack does not reach my code. How can I catch this error? Or is there a more appropriate way to be drawing the image to the imageView that can avoid this error?

like image 875
Milk Avatar asked Feb 27 '17 21:02

Milk


2 Answers

The Bitmap is too large in size and the Bitmap object cannot handle it. Thus, ImageView should have the same problem. Solution: resize the image either in programs such as paint.net, or set a fixed size for the bitmap and scale it.

Before I go further, your stacktrace links to the drawing of the bitmap, not creating the object:

at android.graphics.Canvas.drawBitmap(Canvas.java:1415)

As such you can do this:

Bitmap image = BitmapFactory.decodeFile(file.getPath());//loading the large bitmap is fine. 
int w = image.getWidth();//get width
int h = image.getHeight();//get height
int aspRat = w / h;//get aspect ratio
int W = [handle width management here...];//do whatever you want with width. Fixed, screen size, anything
int H = W * aspRat;//set the height based on width and aspect ratio

Bitmap b = Bitmap.createScaledBitmap(image, W, H, false);//scale the bitmap
imageView.setImageBitmap(b);//set the image view
image = null;//save memory on the bitmap called 'image'

Or, as mentioned here, you can use Picasso as well

NOTE

The image you attempted to load in when the stacktrace is from, is 213828900 bytes, which is 213mb. This is probably an image with very high resolution, as the bigger in size they are, the bigger in bytes they are.

With images that big, the method with scaling may not work as it sacrifices too much of the quality. With images that big, Picasso or Glide may be the only options that loads in the pictures without a too big loss of resolution.

like image 32
Zoe stands with Ukraine Avatar answered Nov 11 '22 10:11

Zoe stands with Ukraine


Any app allow user pick picture as background or draw somewhere, it must encount the problem, if user pickup a panoramic photograph or big picture your app must force close, and YOU HAVE NO CHANCE TO PREVENT THE MISTACK, because you can't catch the Exception.

Ok, I just need catch the Exception and tell user we can't load the picture then finish, it too redundant to use Picasso or such library for the additional function, android coding is suffer and I don't want make it more suffer.

finally, I found the code in core.java.android.view.DisplayListCanvas, there is define a max image size with variable MAX_BITMAP_SIZE

private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB

You couldn't read the variable in your program, it's define as private(but if you have any way to read the variable please let me know), and here is the part code that throw RuntimeException:

int bitmapSize = bitmap.getByteCount();
if (bitmapSize > MAX_BITMAP_SIZE) {
    throw new RuntimeException(
        "Canvas: trying to draw too large(" + bitmapSize + "bytes) bitmap.");
    }

I just copy the part above, check the size of bitmap in my code, if it over 100M then show message to user the message I mention above then finish.

If your case is the same with me, hope it help you.

like image 143
Eyes Blue Avatar answered Nov 11 '22 09:11

Eyes Blue