Frage

Ich bin derzeit auf der Suche nach einem Weg, um ein Schwarz-Weiß-Bitmap zu verwenden, um den Alphakanal eines anderen Bitmap oder Drawable auf Android zu maskieren. Ich bin neugierig, was der beste Weg, dies zu tun ist. Ich habe auf jeden Fall ein paar Ideen, wie dies zu tun, aber sie sind nicht optimal.

Ich muss in der Lage, jeder so oft eine neue Maske auf das Bild anzuwenden (die Schwarz-Weiß-Bitmap wird alle paar Sekunden aus).

Jedes Feedback, wie dies zu erreichen, würde sehr geschätzt werden.

War es hilfreich?

Lösung

Ich habe es funktioniert, so dass es so etwas wie diese

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

Andere Tipps

Meine Lösung liegt in der Nähe @ over_optimistic-Lösung, weniger ein saveLayer () -Aufruf. Ich benutze ein Auslosungs anstelle eines Weges Maske, in meinem Fall war es eine Disc.

Ich erklärte diese Variablen als Felder (es ist gute Praxis Speicher außerhalb der OnDraw-Methode zuzuteilen):

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

Dann irgendwo außerhalb von OnDraw (), Setup der Objekte:

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

Dann schließlich die OnDraw () -Methode wendet die Maske:

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

Für ein besseres Verständnis des Transfer-Modi, beziehen ich mich auf http://ssp.impulsetrain.com/ porterduff.html . Die Seite ist interessant, schön zu lesen. Danach wird mit der gleichen Art von Code können Sie viel mehr als eine einfache Maske acheive!

Ich habe ein maskierbare Layout. Es ist ein framelayout, wo Sie die xporterduffmode und die Maske specifiy kann. Sie können es hier finden: https://github.com/christophesmet/android_maskable_layout

Ich bin mir nicht ganz klar, was Sie vorhaben, für, aber ich glaube, dass eine Kombination von BitmapDrawable und LayerDrawable arbeiten kann. BitmapDrawable können Sie Ihre Bitmaps als Drawables verwenden, und dann können Sie LayerDrawable verwenden Sie die Maske auf einer anderen Drawable Schicht.

Mit dem Xfermodes Beispiel in der API war ich in der Lage Demo einen PorterDuffXfermode zu einem Lack-Objekt angewandt zu verwenden, um zu verschmelzen zwei Bitmaps auf einer Leinwand. Dies funktioniert genau, wie ich brauche es.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top