在画布上绘画时,PorterDuff源和目标是指什么?
我一直想弄明白这一点,但在Google上找到的答案涉及Android的画布的非常具体的问题,我还没有找到关于这个主题的任何101解释。即使Android文档使用位图,而不是绘制形状。在画布上绘画时,PorterDuff源和目标是指什么?
具体问题:
我需要在画布上绘制椭圆形和路径。并根据documentation颜色来源与一种颜色,目的地出另一种颜色和重叠区域,无论是源或目的地,第三种颜色。我正在尝试在屏幕外画布中完成所有这些操作。但是上面的某些步骤会出现问题,并且在尝试以任何方式组合它们时会变得更糟。
-
码 -
Bitmap bmp = Bitmap.CreateBitmap (720, 720, Bitmap.Config.Argb8888); Canvas c = new Canvas (bmp); Paint paint = new Paint(); paint.SetARGB (255, 255, 0, 0); c.DrawOval (200, 200, 520, 520, paint); //assumed destination paint.SetARGB (255, 0, 0, 255); paint.SetXfermode (new PorterDuffXfermode (PorterDuff.Mode.*)); //replace mode here paint.SetStyle (Paint.Style.Fill); Path path = new Path(); path.MoveTo (c.Width/2f, c.Height/2f); foreach (var m in measurements) { //calculations float x = xCalculatedValue float y = yCalculatedValue path.LineTo (x, y); } path.LineTo (c.Width/2f, c.Height/2f); c.DrawPath (path, paint); //assumed source
来源了 -
这不是什么吸引XOR应该吸取。
- 目的地了 -
可正常工作。
- 来源 -
此画什么源之上应该。
- 目的地中 -
此画什么目的应该。
更一般的问题:
在这种情况下源和目标是指什么?直觉上我会假设目标是画布位图的当前状态,而源是由canvas.Draw *和Paint PortedDuff.Mode添加的矩阵。但似乎并非如此。
编辑:这基本上是我后面的效果,其中“星”是一个动态路径。根据重叠颜色三种不同的颜色。
编辑2:约克沉做得很好回答的问题实际。但对于任何想获得类似效果的人来说,这是最终的代码。
Bitmap DrawGraphBitmapOffscreen()
{
Bitmap bmp = Bitmap.CreateBitmap (720, 720, Bitmap.Config.Argb8888);
Canvas c = new Canvas (bmp);
// Replace with calculated path
Path path = new Path();
path.MoveTo (c.Width/2f, c.Height/2f);
path.LineTo (263, 288);
path.LineTo (236, 202);
path.LineTo (312, 249);
path.LineTo (331, 162);
path.LineTo (374, 240);
path.LineTo (434, 174);
path.LineTo (431, 263);
path.LineTo (517, 236);
path.LineTo (470, 312);
path.LineTo (557, 331);
path.LineTo (479, 374);
path.LineTo (545, 434);
path.LineTo (456, 431);
path.LineTo (483, 517);
path.LineTo (407, 470);
path.LineTo (388, 557);
path.LineTo (345, 479);
path.LineTo (285, 545);
path.LineTo (288, 456);
path.LineTo (202, 483);
path.LineTo (249, 407);
path.LineTo (162, 388);
path.LineTo (240, 345);
path.LineTo (174, 285);
path.LineTo (263, 288);
path.Close();
Paint paint = new Paint();
paint.SetARGB (255, 255, 0, 0);
paint.SetStyle (Paint.Style.Fill);
c.DrawPath (path, paint);
paint.SetARGB (255, 0, 0, 255);
paint.SetXfermode (new PorterDuffXfermode (PorterDuff.Mode.SrcIn));
c.DrawOval (200, 200, 520, 520, paint);
paint.SetARGB (255, 255, 255, 255);
paint.SetXfermode (new PorterDuffXfermode (PorterDuff.Mode.DstOver));
c.DrawOval (200, 200, 520, 520, paint);
return bmp;
}
什么PorterDuff源和目标引用在画布上绘制时?
我之前的评论是不正确的,对任何不方便抱歉。
经过一番深入的研究,我写了一些演示来深入解释一下。为了帮助您了解什么是源和目的地,请参阅。
首先,看看下面的代码:
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
Paint paint = new Paint();
//Set the background color
canvas.DrawARGB(255, 139, 197, 186);
int canvasWidth = canvas.Width;
int r = canvasWidth/3;
//Draw a yellow circle
paint.Color = Color.Yellow;
canvas.DrawCircle(r, r, r, paint);
//Draw a blue rectangle
paint.Color = Color.Blue;
canvas.DrawRect(r, r, r * 2.7f, r * 2.7f, paint);
}
我重写OnDraw
方法,设置一个绿色的背景,再画一个黄色圆圈和一个蓝色的矩形,效果:
以上是我们在绘制Canvas
时的正常程序,我没有使用任何PorterDuffXfermode
,我们来分析一下它的过程:
首先,我们调用
canvas.DrawARGB(255, 139, 197, 186)
方法用单一颜色绘制整个Canvas
,在这个画布的每个像素具有相同的ARGB
值:(255, 139, 197, 186)
。由于ARGB
中的alpha值是255而不是0,因此每个像素都是不透明的。其次,当我们执行
canvas.DrawCircle(r, r, r, paint)
方法时,Android会在您定义的位置绘制一个黄色圆圈。 ARGB值为(255,139,197,186)
的所有像素将被替换为黄色像素。 黄色像素是源,ARGB值是(255,139,197,186)
的像素是目的地。我会在稍后解释。三,在执行
canvas.DrawRect(r, r, r * 2.7f, r * 2.7f, paint)
方法后,Android会绘制一个蓝色的矩形,这个矩形的所有像素都是蓝色的,这些蓝色像素会替换同一位置的其他像素。所以蓝色矩形可以在Canvas
上画出。
其次,我用的Xfermode
模式,PorterDuff.Mode.Clear
:
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
Paint paint = new Paint();
//Set the background color
canvas.DrawARGB(255, 139, 197, 186);
int canvasWidth = canvas.Width;
int r = canvasWidth/3;
//Draw a yellow circle
paint.Color = Color.Yellow;
canvas.DrawCircle(r, r, r, paint);
//Use Clear as PorterDuffXfermode to draw a blue rectangle
paint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.Clear));
paint.Color = Color.Blue;
canvas.DrawRect(r, r, r * 2.7f, r * 2.7f, paint);
paint.SetXfermode(null);
this.SetLayerType(LayerType.Software, null);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//I found that PorterDuff.Mode.Clear doesn't work with hardware acceleration, so you have add this code
}
效果:
我们来分析一下它的过程:
首先,我们调用
canvas.DrawARGB(255, 139, 197, 186)
方法将整个Canvas
画成单色,每个像素都是不透明的。二,我们拨打
canvas.DrawCircle(r, r, r, paint)
的方法在Canvas
上画一个黄色的 圈。三,执行
paint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.Clear))
,将油漆PorterDuff
型号设置为Clear
。第四,拨打
canvas.DrawRect(r, r, r * 2.7f, r * 2.7f, paint)
绘制一个蓝色的矩形,最后它显示一个白色的矩形。
为什么它显示一个白色矩形?通常,当我们调用canvas.DrawXXX()
方法时,我们会传递一个Paint
参数,当Android执行绘制方法时,它会检查绘图是否有Xfermode
模式。如果不是,则图形将直接覆盖在相同位置处的Canvas
中的像素。否则,将根据Xfermode
模式更新Canvas
中的像素。
在我的例子,当执行canvas.DrawCirlce()
方法,Paint
并未有Xfermode
模式,让黄圈直接覆盖像素Canvas
。但是当我们呼叫canvas.DrawRect()
绘制一个矩形时,Paint
的值为Xfermode
值PorterDuff.Mode.Clear
。 然后Android会在内存中绘制一个矩形,这个矩形中的像素有一个名字:Source。 内存中的矩形在Canvas
中有一个对应的矩形,对应的矩形称为: 目标。
源像素和目标像素的ARGB
的值的ARGB
根据由Xfermode
定义的规则计算出的值,它会计算最终的ARGB值。然后用最终的ARGB
值更新目标像素的ARGB
值。
在我的例子中,Xfermode
是PorterDuff.Mode.Clear
,它要求目标像素ARGB
变成(0,0,0,0)
,这意味着它是透明的。所以我们用canvas.DrawRect()
的方法在Canvas
中画一个透明的矩形,因为Activity
本身有一个白色的背景色,所以它会显示一个白色的矩形。
编辑:
要实现你的图片发布功能,我写了一个演示:
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
Paint paint = new Paint();
paint.SetARGB(255, 255, 0, 0);
RectF oval2 = new RectF(60, 100, 300, 200);
canvas.DrawOval(oval2, paint);
paint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.*));
Path path = new Path();
paint.SetStyle(Paint.Style.Fill);
paint.SetARGB(255, 0, 0, 255);
path.MoveTo(180, 50);
path.LineTo(95, 240);
path.LineTo(255, 240);
path.Close();
this.SetLayerType(LayerType.Software, null);
canvas.DrawPath(path, paint);
paint.SetXfermode(null);
}
当使用不同Xfermode
,它们的效果:
Xor,SrcOut, Screen,Lighten, Darken,Add。
正如你所看到的,你可以使用不同的颜色和不同的Xfermode
来达到你的效果。
@JaanTohver,你解决了你的问题吗? –
辉煌。非常感谢。 “然后Android会在内存中绘制一个矩形,矩形中的像素有一个名字:Source。内存中的矩形在Canvas中有一个对应的矩形,相应的矩形称为:destination。”这正是我所追求的。我认为目的地是整个画布。 – JaanTohver
你想要什么效果,在画布上画一个椭圆形和一条路径?为什么你使用'PorterDuffXfermode'?如果你只需要绘制一个椭圆形和一条路径,就不需要使用'PorterDuffX'。 –
我添加了一张图片来解释我想要做的事情。我不确定alpha合成是最好的解决方案,但它是唯一想到的。这个问题不仅仅是一个实际的解决方案,我想了解在画布上一个接一个地绘制事物的上下文中引用的源和目的地。 – JaanTohver
所以你想绘制一个椭圆形和多边形,然后使用'PorterDuffXfermode'来实现你所发布图片中的效果? –