0

I have this code

 public void DetectFacesInImage(View view)
    {
        BitmapFactory.Options bitmapFactoryOptions=new BitmapFactory.Options();
        bitmapFactoryOptions.inPreferredConfig= Bitmap.Config.RGB_565;
        //int resID = getResources().getIdentifier(picturePath , "drawable", getPackageName());

        myBitmap=BitmapFactory.decodeFile(picturePath,bitmapFactoryOptions);
        int width=myBitmap.getWidth();
        int height=myBitmap.getHeight();
        detectedFaces=new FaceDetector.Face[number_of_faces];
        FaceDetector faceDetector=new FaceDetector(width,height,number_of_faces);
        number_of_faces_detected = faceDetector.findFaces(myBitmap, detectedFaces);
        Canvas canvas = new Canvas(myBitmap);// line 70 the point where it crashes
        Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
        //canvas.drawBitmap(overlay, 0, 0, paint);
        paint.setColor(Color.GREEN);
        paint.setStyle(Paint.Style.STROKE); 
        paint.setStrokeWidth(3);
        PointF midPoint=new PointF();

        for(int count=0;count<number_of_faces_detected;count++)
        {
            Face face=detectedFaces[count];

            face.getMidPoint(midPoint);

            float eyeDistance=face.eyesDistance();
            canvas.drawRect(midPoint.x-eyeDistance, midPoint.y-eyeDistance, midPoint.x+eyeDistance, midPoint.y+eyeDistance, paint);
        }


    }

I want to draw the rectangle on the top of the bitmap. The bitmap is received through intent is is used like this

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detect_faces);
       // getActionBar().setDisplayHomeAsUpEnabled(true);
        Intent intent = getIntent();
        ImageView imageView = (ImageView) findViewById(R.id.imgView);
        picturePath = intent.getStringExtra(GetFaceActivity.PICTURE_PATH);
        imageView.setImageBitmap(BitmapFactory.decodeFile(picturePath));
        //imageView.setOnTouchListener(this);

    }

but the code is crashing with error Immutable bitmap passed to Canvas constructor. What am i doing wrong here ?

Here is the stack trace

10-14 20:01:34.763: E/AndroidRuntime(31137): FATAL EXCEPTION: main
10-14 20:01:34.763: E/AndroidRuntime(31137): java.lang.IllegalStateException: Could not execute method of the activity
10-14 20:01:34.763: E/AndroidRuntime(31137):    at android.view.View$1.onClick(View.java:3098)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at android.view.View.performClick(View.java:3620)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at android.view.View$PerformClick.run(View.java:14322)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at android.os.Handler.handleCallback(Handler.java:605)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at android.os.Handler.dispatchMessage(Handler.java:92)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at android.os.Looper.loop(Looper.java:137)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at android.app.ActivityThread.main(ActivityThread.java:4507)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at java.lang.reflect.Method.invokeNative(Native Method)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at java.lang.reflect.Method.invoke(Method.java:511)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:978)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at dalvik.system.NativeStart.main(Native Method)
10-14 20:01:34.763: E/AndroidRuntime(31137): Caused by: java.lang.reflect.InvocationTargetException
10-14 20:01:34.763: E/AndroidRuntime(31137):    at java.lang.reflect.Method.invokeNative(Native Method)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at java.lang.reflect.Method.invoke(Method.java:511)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at android.view.View$1.onClick(View.java:3093)
10-14 20:01:34.763: E/AndroidRuntime(31137):    ... 11 more
10-14 20:01:34.763: E/AndroidRuntime(31137): Caused by: java.lang.IllegalStateException: Immutable bitmap passed to Canvas constructor
10-14 20:01:34.763: E/AndroidRuntime(31137):    at android.graphics.Canvas.<init>(Canvas.java:133)
10-14 20:01:34.763: E/AndroidRuntime(31137):    at com.example.face_tag_upload.DetectFaces.DetectFacesInImage(DetectFaces.java:70)
10-14 20:01:34.763: E/AndroidRuntime(31137):    ... 14 more
Ankuj
  • 713
  • 3
  • 10
  • 27
  • Please post the LogCat logging, showing the stacktrace of the crashing. – Ridcully Oct 14 '12 at 14:45
  • can you please highlight the line: DetectFaces.java:70 – Soham Oct 14 '12 at 14:49
  • what I get is the bitmap needs to be modifiable or i.e. mutable. But I dont want to create a copy of it. i just want to draw ractangles on top of it. Is there any other method ? – Ankuj Oct 14 '12 at 14:49

1 Answers1

1

If you are working with API Level 11 and up then you need to specify inMutable as part of your BitMapFactory.Options, so;

BitmapFactory.Option bitmapFactoryOptions = new BitmapFactory.Options();
bitmapFactoryOptions.inPreferredConfig = Bitmap.Config.RGB_565;
bitmapFactoryOption.inMutable = true;

If you want to go earlier than API Level 11 then you will want to make a mutable bitmap using the following snippet;

Bitmap immutableBitmap = BitmapFactory.decodeFile(picturePath, bitmapFactoryOptions);
int left = 0;
int top = 0;
int width = immutableBitmap.getWidth();
int height = immutableBitmap.getHeight();
boolean hasAlpha = immutableBitmap.hasAlpha();
Bitmap mutableBitmap = immutableBitmap.createBitmap(width, height, hasAlpha);
Canvas c = new Canvas();
c.setDevice(mutableBitmap);
c.drawBitmap(immutableBitmap, left, top, paint);

The paint variable comes from your pre-existing code.

This answer writes the original bitmap to disk and then creates a mutable version of the bitmap, avoiding the need to have two bitmaps in memory.

Community
  • 1
  • 1
marcus.ramsden
  • 2,633
  • 1
  • 22
  • 33
  • But here you are creating a copy of bitmap for API level less than 11. Isn't there any other method where I don't have to create a copy ? – Ankuj Oct 14 '12 at 14:55
  • Unfortunately I believe that you have to create a copy of the bitmap. If you are worried about having the same bitmap lying around then the link I added to my answer avoids the need for two bitmaps. – marcus.ramsden Oct 14 '12 at 14:59
  • Thanx marcus that did help but alas the rectangles are still not visible on the bitmap even though the code detects 5 faces – Ankuj Oct 14 '12 at 15:01
  • was able to solve the issue I was not updating my imageview with the modifed bitmap – Ankuj Oct 14 '12 at 16:32