Reputation: 1810
I noticed this (what appears to be a bug) when viewing saved bitmaps on my desktop and I could barely see the checkered pattern through the image file. I did a simple experiment:
Bitmap bitmap = new Bitmap(300, 200, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.argb(150, 0, 255, 0));
canvas.drawColor(Color.RED);
canvas.drawRect(20, 20, 280, 180, paint);
Log.d("alpha-bug", "Alpha at 30, 30 is "
+ Color.alpha(bitmap.getPixel(30, 30))
);
to verify. The above logs Alpha at 30, 30 is 254
. The correct alpha is 255
. I get 254 regardless of what the alpha of the shape I'm drawing is. I'm assuming this is a rounding error. Has anyone else come across this? Is this expected and if so why? If not, any ideas on how to get around it?
Upvotes: 2
Views: 404
Reputation: 5044
Yes, seems like a bug to me.
A workaround can be using another Bitmap
to draw the half-transparent shape to, and then draw that bitmap using the drawBitmap
method. The background of that other bitmap is transparent, and this way (apparently), the shape will be drawn properly. (Or if you're reusing the bitmap, you can fill it with transparent using drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
.)
Example code and output:
Bitmap test = Bitmap.createBitmap(250, 190, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(test);
{ // draw opaque background
Paint p = new Paint();
p.setARGB(255, 0, 0, 0);
c.drawPaint(p);
}
Paint circlePaint = new Paint();
circlePaint.setARGB(128, 255, 255, 255);
Bitmap b;
c.drawText("drawCircle", 30, 40, circlePaint);
c.drawText("drawBitmap", 140, 40, circlePaint);
{ // draw a circle into a temporary bitmap as workaround
b = MipMap.allocateBitmapSafely(100, 100);
Canvas ca = new Canvas(b);
ca.drawCircle(50, 50, 50, circlePaint);
System.out.println("drawCircle (in temporary bitmap) color: " + Integer.toHexString(b.getPixel(50, 50)));
}
{ // draw circle with circle-drawing method
c.drawCircle(70, 100, 50, circlePaint);
System.out.println("drawCircle color: " + Integer.toHexString(test.getPixel(70, 100)));
}
{ // draw circle from the saved bitmap with bitmap-drawing method
c.drawBitmap(b, 130, 50, null);
System.out.println("drawBitmap color: " + Integer.toHexString(test.getPixel(170, 100)));
}
String filename = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test.png";
FileOutputStream out = null;
try {
out = new FileOutputStream(filename);
test.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
} finally {
try {
out.close();
} catch (IOException e) {
}
}
Console output:
drawCircle (in temporary bitmap) color: 80ffffff
drawCircle color: fe818181
drawBitmap color: ff808080
In the image, the color of the left circle is (254, 129, 129, 129), the right one is (255, 128, 128, 128). So not only is the alpha 254 instead of 255 on the left, the R, G and B values are off by 1 as well.
P.S.: We should report this to Google because this is an overkill for a workaround.
Upvotes: 1