问题描述
我正在尝试使用Canvas更改形状和文本的交集颜色. 我有2种形状和1种带有不同颜料的文本.
I'm trying to change color of intersection of shapes and text using Canvas. i have 2 shapes and 1 text with different paints.
这没有任何PorterDuffXfermode
,并且PorterDuffColorFilter
模式已添加到任何绘画中.我希望形状的交集是特定的颜色,例如白色,而文本则是红色或白色,如下图所示.
This is without any PorterDuffXfermode
, and PorterDuffColorFilter
mode added to any paint. I want intersection of shapes to be particular color, for example white, and text red or white like the images below.
在我的示例中,文本位于底部,中间的圆圈和上方的矩形,但是它并不重要,我只是想弄清楚它是如何工作的,以及应该如何将交集设置为特定的颜色.
In my example, text is at the bottom, circle middle and rectangle above but it's insignificant, i'm just trying to figure out how it works and how should intersection can be set to particular color.
如您在此图像中所见背景为黑色,圆圈为白色,文本为黑色.当圆圈重叠时,圆圈的交点变为黑色,文本的重叠部分变为白色.
As you can see in this image background is black, circles are white and text is black. When circles overlap intersection of circles turns to black and overlapping section of text turns to white.
我可以做到
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));
如果圆形和矩形均为白色,背景为黑色.当我将背景色更改为任何其他颜色时,文本不可见,形状为黑色.
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.
我还想知道如何获得类似于此图像的类似结果可以将圆形,矩形和文本的重叠部分设置为特定颜色吗?
I also wonder how can i get similar results like in this image Can overlapping sections for circle, rectangle and text can be set to specific color?
推荐答案
和:
PorterDuff
-
(1)是的,我们可以使用
PorterDuff.Mode
(Mode.ADD
):PorterDuff
(1) Yes we can with
PorterDuff.Mode
(Mode.ADD
):PorterDuff.Mode模式= Mode.ADD;
PorterDuff.Mode mode = Mode.ADD;
(2)
Canvas
的背景必须为transparent
,compositing
才能正常工作.如果您需要任何其他背景颜色,那么我们需要在单独Canvas
上进行合成.然后,将图形复制到原始的Canvas
.(2) The
Canvas
background must betransparent
for thecompositing
to work.If you need any other background color then we need to do the compositing on a separateCanvas
.Then we copy the drawing to the originalCanvas
.这是代码输出(
PorterDuff
决定混合颜色; O():Here is the code output (
PorterDuff
decides the blend color ;O( ):- (A1 :)是的,可以(很费力)完成.差不多完成了,但是很有信心.这是几乎完成的图像(我必须在此答案中使用几乎所有内容,必须是一种更简单的方法...):
- (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...):
@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
路口测试
使用 RectF 包含并相交:
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.
具有
setColorFilter
和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
自定义
PorterDuff
听起来您需要
Custom PorterDuff
.这是一些代码,可让您大致了解如何编写代码(Android
使用以C++
编写的库).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 inC++
).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
请参见 PorterDuff ,
PorterDuff.Mode
,PorterDuffXfermode
,ColorFilter
, ColorMatrix , ColorMatrixColorFilter , PorterDuffColorFilter ,Canvas
,Color
.See PorterDuff,
PorterDuff.Mode
,PorterDuffXfermode
,ColorFilter
,ColorMatrix, ColorMatrixColorFilter, PorterDuffColorFilter,Canvas
,Color
.这篇关于Android Canvas更改形状和文本相交的颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!