以编程方式创建位图掩码

时间:2013-01-28 22:05:02

标签: android

我在onDraw()中有这段代码。

radius = drawGmpImage(this.gmpImage, canvas);
canvas.drawCircle(kHorizontalOffset, kScreenVerticalOffset, radius , maskPaint);

drawGmpImage创建一个复杂的图形,这个图形上绘有许多线条。这是一个我无法改变的库函数。线条是多边形,可以延伸到圆的圆周之外。

需要“消除”在圆圈外面绘制的所有内容。

这是来自iOS的端口,原始开发人员解决方案是使用一个简单的位图蒙版,存储为资源,其透明圆圈与绘制的圆的大小相匹配。简单地在绘制的圆上绘制位图具有所需的效果,但在Android上不是一个选项,因为我需要支持所有可能的分辨率和比率。

因此,canvas.drawCircle()调用是我尝试掩盖圆圈外的所有内容的开始。它工作得很好,因为在我绘制的圆上绘制一个实心圆,这样剩下的唯一东西就是绘制圆周外的多边形线。半径是绘制圆的半径。

如何将其反转,以便留下圆圈的内容?

2 个答案:

答案 0 :(得分:7)

为什么你可以花几个小时做某事,放弃,提出问题,然后在20分钟后偶然发现答案?生活的乐趣。

Path path = new Path();
path.addCircle(kHorizontalOffset, kScreenVerticalOffset, radius, Path.Direction.CW);
canvas.clipPath(path);

我错过了将采用任何路径并将其用作剪辑区域的clipPath方法。将我的掩蔽圈添加到路径中就完全符合我的需要。

[编辑]

这很好用,但是有问题。如果打开硬件加速,它不起作用。我可以关闭加速,但是在剩下的平局中我失去了很多表现。这很复杂。

以下是我最终解决的问题:

onSizeChanged()中,创建位图蒙版。我使用这个颜料在位图的正确位置绘制一个透明圆圈。关键是使用PorterDuffXfermode

 maskPaint = new Paint();
 maskPaint.setColor(Color.TRANSPARENT);
 maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
 maskPaint.setStyle(Paint.Style.FILL);

然后创建位图

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {

    super.onSizeChanged(w, h, oldw, oldh);

    createMask(w,h,this.radius);

}

private void createMask(int w,int h, int radius){

    if (mask!=null){mask.recycle();}

    mask = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    Canvas maskCanvas = new Canvas(mask);
    maskCanvas.drawCircle(w, h, radius, maskPaint);

}

然后在onDraw()中,我只是在整个视图上绘制遮罩:

@Override
protected void onDraw(Canvas canvas){

    // draw the image();
    setRadius(drawGmpImage(this.gmpImage, canvas));
    canvas.drawCircle(kHorizontalOffset, kScreenVerticalOffset, radius , maskPaint);

    // overlay the mask bitmap
    if (mask != null) {
        canvas.drawBitmap(mask, 0f, 0f, bitmapPaint);
    }

如果半径改变,则重新创建遮罩:

 private void setRadius(int radius){

     this.radius = radius;
     createMask(kHorizontalOffset, kScreenVerticalOffset, radius);

 }

答案 1 :(得分:1)

我不知道如何使用蒙版实现这一点,因此另一种方法:

你可以用特定的颜色绘制半径,比如黑色。

来自其中一个角落的Floodfill。我之前创建了一个Floodfill算法并不是很困难。从左上角开始,将该像素设置为所需的颜色。然后你看看邻近的像素。如果它们是黑色,则停在那个方向,否则,你改变颜色并再次查看相邻的像素。

祝你好运