【问题标题】:Masking a Drawable/Bitmap on Android在 Android 上屏蔽 Drawable/Bitmap
【发布时间】:2011-02-07 02:37:17
【问题描述】:

我目前正在寻找一种方法来使用黑白位图来掩盖另一个位图或 Android 上的 Drawable 的 alpha 通道。我很好奇最好的方法是什么。对于如何做到这一点,我当然有一些想法,但它们并不是最佳的。

我需要能够经常对图像应用新蒙版(黑白位图每隔几秒就会改变一次)。

我们将不胜感激任何有关如何实现这一目标的反馈。

【问题讨论】:

  • 我正在尝试使用遮罩位图的黑色部分将另一个位图/Drawable 上相应像素的 Alpha 通道设置为 0。

标签: android bitmap mask drawable


【解决方案1】:

我的解决方案接近@over_optimistic 的解决方案,少了一个 saveLayer() 调用。我使用 Drawable 蒙版而不是路径,在我的情况下它是一张光盘。

我将这些变量声明为字段(最好在 onDraw 方法之外分配内存):

private Paint maskingPaint = new Paint();
private Drawable mask = <insert your drawable here>

然后,在 onDraw() 之外的某个地方设置对象:

// Xfermode won't work if hardware accelerated
setLayerType(View.LAYER_TYPE_SOFTWARE, null);

// Using destination shape as a mask
// For a good explanation of PorterDuff transfer modes : http://ssp.impulsetrain.com/porterduff.html
maskingPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
maskingPaint.setAntiAlias(true);

// Position the mask
mask.setBounds(<insert your mask bounds here>);

最后,onDraw() 方法应用掩码:

@Override
protected synchronized void onDraw(Canvas canvas)
{
    // Draw the mask first, making it the PorterDuff destination
    mask.draw(canvas);

    // Save the layer with the masking paint, that will be applied on restore()
    // Using CLIP_TO_LAYER_SAVE_FLAG to avoid any overflow of the masked image outside the mask bounds.
    Rect bounds = mask.getBounds();
    canvas.saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, maskingPaint, 
            Canvas.CLIP_TO_LAYER_SAVE_FLAG);

    // Draw the shape offscreen, making it the PorterDuff source
    super.onDraw(canvas);

    // Apply the source to the destination, using SRC_IN transfer mode
    canvas.restore();
}

为了更好地理解传输模式,我参考了http://ssp.impulsetrain.com/porterduff.html。 那一页读起来很有趣。之后,使用相同类型的代码,您将能够实现的不仅仅是简单的掩码!

【讨论】:

  • 完美解决方案。其他的有点太长了。
  • IMO 比公认的答案更好,我更喜欢可绘制路径
【解决方案2】:

我做了一个可屏蔽的布局。 这是一个框架布局,您可以在其中指定 xporterduffmode 和掩码。 你可以在这里找到它:https://github.com/christophesmet/android_maskable_layout

【讨论】:

    【解决方案3】:

    我让它工作了,所以它是这样的

        // we first same the layer, rectF is the area of interest we plan on drawing
        // this will create an offscreen bitmap
        canvas.saveLayer(rectF, null, Canvas.MATRIX_SAVE_FLAG
                | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
                | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
                | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
    
        // draw our unmasked stuff
        super.draw(canvas);
        // We same a layer again but this time we pass a paint object to mask
        // the above layer
        maskPaint = new Paint()
        maskPaint.setColor(0xFFFFFFFF);
        maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
    
        canvas.saveLayer(rectF, maskPaint,
                Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG
                        | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
                        | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
                        | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
        // we draw the mask which is black and white. In my case
        // I have a path, and I use a blurPaint which blurs the mask slightly
        // You can do anti aliasing or whatever you which. Just black & white
        canvas.drawPath(path, blurPaint);
        // We restore twice, this merges the results upward
        // as each saveLayer() allocates a new drawing bitmap
        canvas.restore();
        canvas.restore();
    

    【讨论】:

    • 如果重写 onDraw 方法,而不是 super.draw(canvas) 应该有 super.onDraw(canvas)。否则,您将陷入无限循环,并出现 StackOverflow 错误。
    • 我在自定义视图的onDraw 中做了与上述相同的事情,但似乎saveLayer 很昂贵,因此我为我的视图设置了一个硬件层 (@987654327 @)。更多信息:stackoverflow.com/a/33483016/4747587
    【解决方案4】:

    使用 API 演示中的 Xfermodes 示例,我能够使用应用于 Paint 对象的 PorterDuffXfermode 将画布上的两个位图混合在一起。这完全符合我的需要。

    【讨论】:

    • 你能补充更多细节吗?
    【解决方案5】:

    我并不完全清楚您的目标,但我相信BitmapDrawableLayerDrawable 的组合可能会起作用。 BitmapDrawable 将允许您将 Bi​​tmaps 用作 Drawable,然后您可以使用 LayerDrawable 将蒙版叠加到另一个 Drawable 之上。

    【讨论】:

    • 如果您希望被遮罩的部分是透明的,这将不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 2012-12-27
    • 2012-01-26
    • 1970-01-01
    • 1970-01-01
    • 2021-07-28
    相关资源
    最近更新 更多