Pregunta

Actualmente estoy buscando una manera de utilizar un mapa de bits en blanco y negro para enmascarar el canal alfa de otro mapa de bits o Disponibles en Android. Soy curioso en cuanto a cuál es la mejor manera de hacer esto es. Ciertamente tengo un par de ideas sobre cómo hacer esto, pero ellos no son óptimas.

Tengo que ser capaz de aplicar una nueva máscara a la imagen de vez en cuando (el mapa de bits en blanco y negro va a cambiar cada pocos segundos).

Cualquier comentario sobre cómo lograr esto sería muy apreciado.

¿Fue útil?

Solución

Lo tengo trabajo, así que es algo como esto

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

Otros consejos

Mi solución está cerca de la solución de @ over_optimistic, menos uno saveLayer () llamada. Yo uso una máscara Disponibles en lugar de un camino, en mi caso se trataba de un disco.

I declaró estas variables como campos (que es buena práctica de asignar la memoria fuera del método onDraw):

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

Entonces, en algún lugar fuera de onDraw (), los objetos de configuración:

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

Entonces, finalmente, el método onDraw () aplica la máscara:

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

Para una mejor comprensión de los modos de transferencia, que se refirió a http://ssp.impulsetrain.com/ porterduff.html . Esa página es bastante interesante para leer. Después de eso, con el mismo tipo de código podrás acheive mucho más que una simple máscara!

Hice un diseño enmascarable. Es un FrameLayout donde se puede specifiy la xporterduffmode y la máscara. Lo puedes encontrar aquí: https://github.com/christophesmet/android_maskable_layout

No estoy del todo claro en lo que vamos a ir, pero creo que una combinación de BitmapDrawable y LayerDrawable puede trabajar. BitmapDrawable le permitirá utilizar sus mapas de bits como dibujables, y luego se puede utilizar LayerDrawable a la capa de la máscara en la parte superior de otro Disponibles.

Usando el ejemplo Xfermodes en el API de demostración I fue capaz de utilizar un PorterDuffXfermode aplicar a un objeto de pintura a mezclarse dos mapas de bits en una lona. Esto funciona exactamente cómo lo necesito a.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top