Problems with color when drawing bitmap in Canvas.

Also, when I apply a color filter to a Bitmap, a black stroke appears on the sides of the images with transparency. I know that this is due to the so-called premultiplied mode, but how can this be circumvented by continuing to use Canvas? Or will only use OpenGL? I watched this video: youtube.com/watch?v=-dK71TVrBLM.

If I understood correctly, this effect can be avoided by dividing all the channels by the alpha value (before drawing the Bitmap itself?), The only question is, did I understand everything correctly and would this help in this particular case? Here are a couple of illustrations: The first is about what happens when applying a colorfilter. (No color / alpha correction, just applying a filter).

After before

The second. Simple drawing of the gradient without any transformations. This is how the picture looks in Photoshop (from the left) - equal color values ​​throughout the image.

enter image description here

After drawing - in the center less - the original color. Then, slowly, red begins to fade (although there is no color gradation in the original version), after which it completely disappears, and blue, suddenly crawls out even stronger. Again, it turns out the same dark border along the radius, only unobtrusive.

Code :

class DrawView extends View { Paint paint; Bitmap bitmap; Rect rect; float[] cmData = new float[]{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0}; ColorMatrix cm; ColorFilter filter; Bitmap icon; public DrawView(Context context) { super(context); rect = new Rect(0,0,200,200); paint = new Paint(Paint.ANTI_ALIAS_FLAG); icon = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher); cm = new ColorMatrix(cmData); filter = new ColorMatrixColorFilter(cm); } @Override protected void onDraw(Canvas canvas) { canvas.drawARGB(80, 102, 204, 255); canvas.translate(100, 100); canvas.save(); canvas.translate(220, 0); canvas.drawBitmap(icon, null, rect, paint); canvas.restore(); paint.setColorFilter(filter); canvas.translate(0, 300); canvas.save(); canvas.translate(220, 0); canvas.drawBitmap(icon, null, rect, paint); canvas.restore(); } 

    1 answer 1

    Dividing by alpha can help, but if you use a depth of 8 bits, you will lose some information when dividing. I think you see it in your second case.

    To better understand why you need to multiply transparency, you need to get acquainted with alpha blending: https://en.wikipedia.org/wiki/Alpha_compositing

    Alpha blending has a rather complex formula:

    enter image description here

    But if the color is multiplied by transparency, the formula becomes much simpler:

    enter image description here

    For better results, I can advise you to find an image without multiplied transparency or to mix a picture with a background using a formula designed for working with multiplied transparency. Also, if you apply any filters, you need to be sure that they handle this case correctly.