views:

98

answers:

1

I have a problem with the following code:

protected void onDraw(Canvas canvas)
{
    Paint paint = new Paint();

    // Draw a blue circle
    paint.setColor(Color.BLUE);
    canvas.drawCircle(100, 100, 50, paint);

    // Draw a red circle where it collides with the blue one
    paint.setXfermode(new AvoidXfermode(Color.BLUE, 0, Mode.TARGET));
    paint.setColor(Color.RED);
    canvas.drawCircle(50, 50, 50, paint);
}

According to the API documentation of AvoidXfermode the tolerance value 0 means that it looks for an EXACT color match. This should work here because I specify the same color as I used for drawing the first circle. But the result is that the red circle is not drawn at all. When I use a tolerance value of 255 instead then it works (red circle is drawn where it collides with the blue one) but that sounds wrong because with such a high tolerance I think it should draw the circle EVERYWHERE.

So what's wrong here? API Documentation? Android? Me?

+1  A: 

Is your canvas bit depth RGB_565 or ARGB_8888? I tested this on both formats. It worked on a 32-bit canvas, but did not work on the 16-bit canvas. The 16-bit image is likely unable to display the exact color you are drawing(0xFF0000FF), so it gets changed oh so slightly (and imperceptibly to human eyes) when you draw the first blue circle. Then, when you perform the avoid, targetting the exact blue with a tolerance of zero, nothing is shown because that true blue is not in the image.

A tolerance of 255 works because that allows the avoid to match the "almost blue" color, and the result will be a circle that is "almost red." If using a tolerance that high is unsettling, try very low tolerances(starting from 1 and going up) until you find one that is small but still matches the "almost blue" that you want to replace.

The ideal solution would be to read the color value of the blue circle after drawing it, and target that exact color. This would be possible if you had the bitmap of the canvas you are working with, and you could call bitmap.getPixel(). However, I don't know of any way to get a canvas's bitmap if you don't already have it(which you don't in the onDraw method).

Tim Olson
Thanks. That's it.
kayahr