Android Canvas change color of intersection of shapes and texts

后端 未结 1 853
鱼传尺愫
鱼传尺愫 2020-12-17 07:02

I\'m trying to change color of intersection of shapes and text using Canvas. i have 2 shapes and 1 text with different paints.

This is without any PorterDuffXf

相关标签:
1条回答
  • 2020-12-17 07:39

    Android Canvas change color of intersection of shapes and texts

    and:

    "If circle and rectangle are both white and background is black. When I change background color to any other color, text is not visible, shapes are black."

    PorterDuff

    • (1) Yes we can with PorterDuff.Mode (Mode.ADD):

      PorterDuff.Mode mode = Mode.ADD;

    • (2) The Canvas background must be transparent for the compositing to work. If you need any other background color then we need to do the compositing on a separate Canvas. Then we copy the drawing to the original Canvas.

    "I also wonder how can i get similar results like in this image"

    Here is the code output (PorterDuff decides the blend color ;O( ):

    (Q1:) "Can overlapping sections for circle, rectangle and text can be set to specific color?"

    • (A1:) Yes it can be done (with much effort). Almost finished but confident it can. here are the almost finished images (I had to use almost all of the stuff in this answer, there must be an easier way...):

    Code

    @Override
    protected void onDraw(Canvas canvas) 
    {
        super.onDraw(canvas);
    
        Paint paint          = new Paint();
        Paint paintClear     = new Paint();
        TextPaint textPaint  = new TextPaint();
        int width            = getWidth();
        int height           = getHeight();
        int x                = 100;
        int y                = 100;
        int radius           = 100;
    
        PorterDuff.Mode mode        = Mode.ADD;      // mode Mode.ADD
    
        paintClear.setStyle(Style.FILL); 
        paint.setStyle(Style.FILL); 
        textPaint.setAntiAlias(true); 
        textPaint.setTextSize(100 * getResources().getDisplayMetrics().density);
        textPaint.setColor(Color.GREEN);    
        textPaint.setStrokeWidth(3);     
    
        // ** clear canvas backgound to white**
        paintClear.setColor(Color.WHITE);
        canvas.drawPaint(paintClear); 
        //canvas.save();
    
        Bitmap compositeBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas compositeCanvas = new Canvas(compositeBitmap);
        paintClear.setColor(Color.TRANSPARENT);
        compositeCanvas.drawPaint(paintClear); 
    
        // ** draw destination circle in red **
        paint.setColor(Color.RED);
        compositeCanvas.drawCircle(x+100, y+100, radius, paint);
    
        // ** set Xfermode **
        paint.setXfermode(new PorterDuffXfermode(mode));
        textPaint.setXfermode(new PorterDuffXfermode(mode));
    
        // ** draw source circle in blue **
        paint.setColor(Color.BLUE);
        compositeCanvas.drawCircle(x-0, y-0, radius, paint);
    
        // ** draw text in Green **
        compositeCanvas.save();
        compositeCanvas.rotate(-45, x, y+150);
        compositeCanvas.drawText("- 65,6", x, y+150, textPaint);
        compositeCanvas.restore();
    
        //copy compositeCanvas to canvas
        canvas.drawBitmap(compositeBitmap, 0, 0, null);
        //canvas.restore();
    }//onDraw
    

    Intersection Testing

    Using RectF contains and intersects:

    public Rect  mBound = new Rect(0  , 0  , 10 , 10);
    public RectF a1     = new Rect(0f , 0f , 10f, 10f);
    public RectF b1     = new Rect(5f , 5f , 20f, 20f);
    public RectF c1     = new Rect(30f, 30f, 40f, 40f);
    
    int boolean hit       = false;
    int boolean intersect = false;
    hit = hitTest(20,15); // returns false
    hit = hitTest(5,5);   // returns true 
    intersect = intersectsTest(a1,b1);// returns true
    intersect = intersectsTest(a1,c1);// returns false
    
    public boolean hitTest(int x, int y) 
    {
        return mBound.contains(x, y); 
    }//
    // Returns true if the two specified rectangles intersect
    public boolean intersectsTest(RectF a, RectF b) 
    {
        return intersects ( a, b);
    }//
    

    Notes

    You indicated you wanted to know more about color drawing, here are some things I toyed with.

    Experiments with setColorFilter and ColorMatrixColorFilter:

    textPaint.setColorFilter(new ColorMatrixColorFilter(getColorMatrix5()));//custom 5
    
    //custom 5
    private ColorMatrix getColorMatrix5() 
    {
        ColorMatrix colorMatrix = new ColorMatrix();
        colorMatrix.setSaturation(0);//make it greyscale
        ColorMatrix blueMatrix = new ColorMatrix(new float[] {
            0, 0, 0, 0, 0, // red
            0, 0, 0, 0, 0, // green
            1, 1, 1, 1, 1, // blue
            1, 1, 1, 1, 1  // alpha
        });
        // Convert, then scale and clamp
        colorMatrix.postConcat(blueMatrix);
        return colorMatrix;
    }//getColorMatrix1
    

    Customise PorterDuff

    It sounds like you need a Custom PorterDuff. Here's some code to give you an idea of how to write one (Android uses a library written in C++).

    public class MyPorterDuffMode
    {
    
        public Bitmap applyOverlayMode(Bitmap srcBmp, Bitmap destBmp)
        {
            int width          = srcBmp.getWidth();
            int height         = srcBmp.getHeight();
            int srcPixels[]    = new int[width * height];
            int destPixels[]   = new int[width * height];
            int resultPixels[] = new int[width * height];
            int aS   = 0, rS = 0, gS = 0, bS = 0;
            int rgbS = 0;
            int aD   = 0, rD = 0, gD = 0, bD = 0;
            int rgbD = 0;
    
            try
            {
                srcBmp.getPixels(srcPixels, 0, width, 0, 0, width, height);
                destBmp.getPixels(destPixels, 0, width, 0, 0, width, height);
                srcBmp.recycle();
                destBmp.recycle();
            }
            catch(IllegalArgumentException e)
            {
            }
            catch(ArrayIndexOutOfBoundsException e)
            {
            }
    
            for(int y = 0; y < height; y++)
            {
                for(int x = 0; x < width; x++)
                {
                    rgbS = srcPixels[y*width + x];
                    aS = (rgbS >> 24) & 0xff;
                    rS = (rgbS >> 16) & 0xff;
                    gS = (rgbS >>  8) & 0xff;
                    bS = (rgbS      ) & 0xff;
    
                    rgbD = destPixels[y*width + x];
                    aD = ((rgbD >> 24) & 0xff);
                    rD = (rgbD >> 16) & 0xff;
                    gD = (rgbD >>  8) & 0xff;
                    bD = (rgbD      )  & 0xff;
    
                    //overlay-mode
                    rS = overlay_byte(rD, rS, aS, aD);
                    gS = overlay_byte(gD, gS, aS, aD);
                    bS = overlay_byte(bD, bS, aS, aD);
                    aS = aS + aD - Math.round((aS * aD)/255f);
    
                    resultPixels[y*width + x] = ((int)aS << 24) | ((int)rS << 16) | ((int)gS << 8) | (int)bS;
                }
            }
            return Bitmap.createBitmap(resultPixels, width, height, srcBmp.getConfig());
        }
    
        // kOverlay_Mode
        int overlay_byte(int sc, int dc, int sa, int da) 
        {
            int tmp = sc * (255 - da) + dc * (255 - sa);
            int rc;
            if (2 * dc <= da) 
            {
                rc = 2 * sc * dc;
            } 
            else 
            {
                rc = sa * da - 2 * (da - dc) * (sa - sc);
            }
            return clamp_div255round(rc + tmp);
        }
    
        int clamp_div255round(int prod) 
        {
            if (prod <= 0) 
            {
                return 0;
            } 
            else if (prod >= 255*255) 
            {
                return 255;
            } 
            else 
            {
                return Math.round((float)prod/255);
            }
        }
    
    }//class MyPorterDuffMode
    

    Code Reference

    See PorterDuff, PorterDuff.Mode,PorterDuffXfermode, ColorFilter,ColorMatrix, ColorMatrixColorFilter, PorterDuffColorFilter, Canvas, Color.

    0 讨论(0)
提交回复
热议问题