Domanda

Attualmente sto cercando un modo per utilizzare una bitmap in bianco e nero per mascherare il canale alfa di un altro bitmap o Drawable su Android. Sono curioso di sapere cosa il modo migliore per farlo è. Io certamente ho un paio di idee su come fare questo, ma non sono ottimali.

Ho bisogno di essere in grado di applicare una nuova maschera per l'immagine ogni tanto (la bitmap in bianco e nero cambierà ogni pochi secondi).

Qualunque feedback su come raggiungere questo sarebbe molto apprezzato.

È stato utile?

Soluzione

I ottenuto che funziona, quindi è qualcosa di simile

    // 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();

Altri suggerimenti

La mia soluzione è vicino a @ di over_optimistic soluzione, meno uno saveLayer () chiamata. Io uso un Drawable maschera invece di un percorso, nel mio caso si trattava di un disco.

I dichiarato queste variabili come campi (è buona pratica per allocare la memoria al di fuori del metodo OnDraw):

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

Poi, da qualche parte al di fuori di OnDraw (), gli oggetti di configurazione:

// 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>);

Poi infine, il metodo OnDraw () applica la maschera:

@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();
}

Per una migliore comprensione delle modalità di trasferimento, ho fatto riferimento a http://ssp.impulsetrain.com/ porterduff.html . Quella pagina è piuttosto interessante da leggere. Dopo di che, con lo stesso tipo di codice che sarete in grado di acheive molto più di una semplice maschera!

Ho fatto un layout mascherabile. E 'un framelayout dove è possibile specifiy la xporterduffmode e la maschera. Lo si può trovare qui: https://github.com/christophesmet/android_maskable_layout

Io non sono del tutto chiaro su quello che stai per andare, ma credo che una combinazione di BitmapDrawable e LayerDrawable può funzionare. BitmapDrawable vi permetterà di utilizzare le bitmap come drawable, e quindi è possibile utilizzare LayerDrawable per stratificare la maschera sopra un'altra Drawable.

Utilizzando l'esempio Xfermodes nella API demo ho potuto utilizzare un PorterDuffXfermode applicato ad un oggetto Paint mescolarsi insieme due bitmap su una tela. Questo funziona esattamente come ho bisogno di.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top