18

私は現在、白黒のビットマップを使用して、Androidの別のビットマップまたはDrawableのアルファチャネルをマスクする方法を探しています。これを行うための最良の方法が何であるかについて私は興味があります。私は確かにこれを行う方法についていくつかのアイデアを持っていますが、それらは最適ではありません。

画像に新しいマスクを頻繁に適用できるようにする必要があります(白黒のビットマップは数秒ごとに変更されます)。

これを達成する方法についてのフィードバックをいただければ幸いです。

4

5 に答える 5

8

私のソリューションは@over_optimisticのソリューションに近く、saveLayer()の呼び出しは1つではありません。パスの代わりにドローアブルマスクを使用します。私の場合はディスクでした。

これらの変数をフィールドとして宣言しました(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を参照しました。そのページは読むのがとても面白いです。その後、同じ種類のコードを使用すると、単純なマスクよりもはるかに多くのことを達成できるようになります。

于 2014-07-30T16:04:05.750 に答える
6

私はそれを動かしたので、それはこのようなものです

    // 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();
于 2012-10-12T20:19:47.857 に答える
4

マスク可能なレイアウトを作成しました。これは、xporterduffmodeとマスクを指定できるフレームレイアウトです。あなたはここでそれを見つけることができます:https ://github.com/christophesmet/android_maskable_layout

于 2014-07-26T11:40:17.083 に答える
2

私はあなたが何をしようとしているのか完全には明確ではありませんが、との組み合わせがうまくいくBitmapDrawableかも しれないと信じていLayerDrawableます。BitmapDrawableを使用すると、ビットマップをDrawableとして使用できます。次に、LayerDrawableを使用して、別のDrawableの上にマスクを重ねることができます。

于 2010-04-12T18:24:28.327 に答える
1

APIデモのXfermodesの例を使用して、Paintオブジェクトに適用されたPorterDuffXfermodeを使用して、キャンバス上の2つのビットマップをブレンドすることができました。これは私が必要とする方法で正確に機能します。

于 2010-04-17T17:08:23.887 に答える