【问题标题】:Android Bitmap Masking (Xfermode) leaves opaque black background behindAndroid Bitmap Masking (Xfermode) 留下不透明的黑色背景
【发布时间】:2016-02-02 13:48:35
【问题描述】:

我有一个自定义视图,在onDraw() 中,我正在尝试执行位图遮罩。我有一个squareBitmap(红色)填充整个视图,我有一个circleBitmap(蓝色)作为遮罩。我正在使用模式:PorterDuff.Mode.DST_IN

我期待的结果是一个红色的圆圈。我明白了,但我也得到了一个黑色的不透明背景。我不想要这个不透明的背景,而应该是透明的。 Figure 1 是我得到的结果,Figure 2 是我正在寻找的结果。

我的代码:(出于这个问题的目的,我已将 onDraw() 中的所有内容都移动了)

protected void onDraw(Canvas canvas) {

    final int width = canvas.getWidth();
    final int height = canvas.getHeight();

    Bitmap circleBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas circleCanvas = new Canvas(circleBitmap);
    Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
    p.setStyle(Paint.Style.FILL_AND_STROKE);
    p.setColor(Color.BLUE);
    circleCanvas.drawCircle(width / 2, height / 2, width / 2, p);

    p.setColor(Color.RED);
    Bitmap squareBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas squareCanvas = new Canvas(squareBitmap);
    final Rect squareRect = new Rect(0, 0, width, height);
    squareCanvas.drawRect(squareRect, p);

    Paint q = new Paint(Paint.ANTI_ALIAS_FLAG);
    canvas.drawBitmap(squareBitmap, 0, 0, q);
    q.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    canvas.drawBitmap(circleBitmap, 0, 0, q);
    q.setXfermode(null);
}


我哪里错了?如何避免这种黑色不透明背景?

【问题讨论】:

  • 尝试DST_OUT 而不是DST_IN。或SRC_IN.
  • @FrankN.Stein 不,它不起作用。现在我得到黑色实心圆圈和红色背景。背景是红色的,因为squareBitmap,但是为什么圆圈是黑色的?理想情况下,圆圈应该是透明的,因此应该是蓝色(背景布局的颜色)。
  • 你应该在这里找到答案:ssp.impulsetrain.com/porterduff.html
  • @FrankN.Stein 谢谢,但此链接提供了有关混合模式如何工作的想法,但没有解释解决我的问题的方法。我终于通过将硬件层设置到我的自定义视图来解决问题。

标签: android android-canvas android-view android-bitmap


【解决方案1】:

似乎要完成Xfermode,我需要将绘图重定向到屏幕外位图。所以添加以下内容解决了我的问题。

canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), q);

但话又说回来,saveLayerdocumentation 表示要避免使用这种方法,因为它很昂贵。建议使用harware layer 代替此方法。

避免使用这种方法,特别是如果提供的边界很大, 或者如果保存标志中省略了 CLIP_TO_LAYER_SAVE_FLAG 范围。建议在 View 上使用硬件层 应用 xfermode、滤色器或 alpha,因为它会执行很多 比这个方法好。

因此,除了saveLayer 方法,我可以通过添加以下内容来修复它:

setLayerType(LAYER_TYPE_HARDWARE, q);

【讨论】:

  • 您是否介意提供完整的示例,显示绘图位图、蒙版以及使用的绘图和 XferMode?谢谢!
  • 我问题中的代码是完整的示例。我有一门课extends View。我有问题中的'onDraw()'方法。我添加使其工作的唯一内容是答案:'setLayerType'。您可能想看看这个真实场景:stackoverflow.com/a/33483600/4747587
猜你喜欢
  • 2018-04-25
  • 1970-01-01
  • 2011-11-15
  • 1970-01-01
  • 2016-02-22
  • 2012-06-26
  • 2015-07-04
  • 1970-01-01
相关资源
最近更新 更多