86
java.lang.IllegalStateException: Immutable bitmap passed to Canvas constructor
at android.graphics.Canvas.<init>(Canvas.java:127)
at app.test.canvas.StartActivity.applyFrame(StartActivity.java:214)
at app.test.canvas.StartActivity$1.onClick(StartActivity.java:163)
at android.view.View.performClick(View.java:4223)
at android.view.View$PerformClick.run(View.java:17275)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4898)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
at dalvik.system.NativeStart.main(Native Method)

I get this crash error from the developer console .. I don't understand what is the problem ..

    BitmapFactory.Options opt = new BitmapFactory.Options();
    opt.inScaled = true;
    opt.inPurgeable = true;
    opt.inInputShareable = true;
    Bitmap brightBitmap = BitmapFactory.decodeResource(getResources(), position, opt); 
    brightBitmap = Bitmap.createScaledBitmap(brightBitmap, 550, 550, false);
    chosenFrame = brightBitmap;
    Bitmap workingBitmap = Bitmap.createBitmap(chosenFrame);
    workingBitmap = Bitmap.createBitmap(workingBitmap); 
    Canvas c = new Canvas(workingBitmap);

I think it's related to this ?

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Yerry Huntry
  • 1,195
  • 2
  • 9
  • 7

5 Answers5

236

You have to convert your workingBitmap to Mutable Bitmap for drawing on Canvas. (Note: this method does not help save memory, it will use extra memory)

Bitmap workingBitmap = Bitmap.createBitmap(chosenFrame);
Bitmap mutableBitmap = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(mutableBitmap);

This answer helps don't waste memory Convert immutable bitmap to a mutable bitmap

Community
  • 1
  • 1
dimetil
  • 3,851
  • 2
  • 29
  • 47
44

BitmapFactory.decodeResource() returns an immutable copy of the bitmap and you cannot draw to its canvas. In order to get its canvas, you need to get a mutable copy of the images' bitmap and that can be done with single line code addition.

opt.inMutable = true;

Add that line to your code and it should address the crash.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
codeFood
  • 1,241
  • 16
  • 16
  • 2
    this should be the answer since it doesnt consume memory which is the case when using bitmap.copy(...) – java Feb 14 '16 at 19:32
  • It' essential to check Bitmap properties and set them before loading Bitmap into memory. Use this answer if memory is an issue, esspecialy it is if you are using bitmap with big dimensions. – Thracian Feb 19 '17 at 11:20
5

Unless you don't want to make your IMMUTABLE bitmap to MUTABLE bitmap, you can save memory by ALWAYS REUSING THE BITMAP

workingBitmap = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(workingBitmap);

However I think this may be same as making the bitmap mutable by calling

workingBitmap.isMutable = true
Ujju
  • 2,723
  • 3
  • 25
  • 35
5

This works as well, I just tested it.

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
return BitmapFactory.decodeByteArray(resultDecoded, 0, resultDecoded.length,options);
Joe
  • 1,316
  • 9
  • 17
1

in order to minimize memory usage, you can check out this post about converting/decoding a mutable bitmap straight from the resources :

https://stackoverflow.com/a/16314940/878126

Community
  • 1
  • 1
android developer
  • 114,585
  • 152
  • 739
  • 1,270