Obito
Obito

Reputation: 69

Android Canvas trying to draw too large Exception

I am testing my app on 5 devices: Samsung Galaxy core, Samsung S6 edge, Moto G4, Xiaomi Redmi note 4 and Xiaomi MiA1. Loading bitmaps works fine on them but on some other it throws java.lang.RuntimeException: Canvas: trying to draw too large. Can you help me find a solution?

Log:

Fatal Exception: java.lang.RuntimeException: Canvas: trying to draw too large(135788800bytes) bitmap. at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:229) at android.view.RecordingCanvas.drawBitmap(RecordingCanvas.java:97) at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:529) at android.widget.ImageView.onDraw(ImageView.java:1367) at android.view.View.draw(View.java:20338) at android.view.View.updateDisplayListIfDirty(View.java:19283) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.draw(View.java:20341) at android.view.View.updateDisplayListIfDirty(View.java:19283) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.updateDisplayListIfDirty(View.java:19274) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.updateDisplayListIfDirty(View.java:19274) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.updateDisplayListIfDirty(View.java:19274) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.updateDisplayListIfDirty(View.java:19274) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.draw(View.java:20341) at com.android.internal.policy.DecorView.draw(DecorView.java:979) at android.view.View.updateDisplayListIfDirty(View.java:19283) at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:686) at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:692) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:800) at android.view.ViewRootImpl.draw(ViewRootImpl.java:3447) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3234) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2769) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1738) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7745) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911) at android.view.Choreographer.doCallbacks(Choreographer.java:723) at android.view.Choreographer.doFrame(Choreographer.java:658) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6938) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

Upvotes: 5

Views: 19475

Answers (4)

Wilson Tran
Wilson Tran

Reputation: 4811

If your app is using Glide:

Glide.with(context).load(uri).into(imageView);

Upvotes: 0

Curio
Curio

Reputation: 1371

You can use Picasso to resize your image:

Picasso.get().load(imageUri).resize(512,512).into(imageView);

In resize method, the 2 numbers are the target width and height of your image. Change them as you like (but don't put too large numbers!).

It worked for me.

Upvotes: 0

Viktor Stojanov
Viktor Stojanov

Reputation: 708

Even if you reduce the file size of your image by compressing it, the Bitmap shown on the phone will still take substantial amount of memory. Bitmap renders every pixel independently and therefore a 4048x3036 pixels image can take up to 48 Mb of memory

The solution would be to reduce the resolution while maintaining desirable detail quality.

Loading Large Bitmaps Efficiently

Upvotes: 1

Chethan Kumar
Chethan Kumar

Reputation: 195

Try to compress your selected image before doing any action.

Here is the code that compress image with equal aspect ratio.

I converted Uri to bitmap

bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);

The i pass the bitmap, maxwidth, minWidth to resize().

resizeBitmap = resize(bitmap, bitmap.getWidth() / 2, bitmap.getHeight() / 2);

resize() method

private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) {
    if (maxHeight > 0 && maxWidth > 0) {
        int width = image.getWidth();
        int height = image.getHeight();
        float ratioBitmap = (float) width / (float) height;
        float ratioMax = (float) maxWidth / (float) maxHeight;

        int finalWidth = maxWidth;
        int finalHeight = maxHeight;
        if (ratioMax > ratioBitmap) {
            finalWidth = (int) ((float) maxHeight * ratioBitmap);
        } else {
            finalHeight = (int) ((float) maxWidth / ratioBitmap);
        }
        image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true);
        return image;
    } else {
        return image;
    }
}

Upvotes: 2

Related Questions