سؤال

أنا أبحث حاليًا عن طريقة لاستخدام صورة نقطية بالأبيض والأسود لإخفاء قناة ألفا من صورة نقطية أخرى أو قابلة للرسمية على Android. أنا فضولي بشأن ما هي أفضل طريقة للقيام بذلك. لدي بالتأكيد بعض الأفكار حول كيفية القيام بذلك ، لكنها ليست مثالية.

أحتاج إلى أن أكون قادرًا على تطبيق قناع جديد على الصورة في كثير من الأحيان (سيتغير نقطات النقط بالأبيض والأسود كل بضع ثوان).

أي ردود فعل حول كيفية تحقيق ذلك ستكون موضع تقدير كبير.

هل كانت مفيدة؟

المحلول

لقد عملت ، لذا فهو شيء من هذا القبيل

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

نصائح أخرى

إن حلي قريب من حل @Over_optimistic ، ومكالمة أقل من Savelayer (). أستخدم قناعًا قابل للسحب بدلاً من المسار ، في حالتي كان قرصًا.

أعلنت هذه المتغيرات كحقول (من الممارسات الجيدة تخصيص الذاكرة خارج طريقة 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. هذه الصفحة مثيرة للاهتمام للغاية للقراءة. بعد ذلك ، مع نفس النوع من التعليمات البرمجية ، ستتمكن من تحقيق أكثر من قناع بسيط!

لقد صنعت تخطيطًا قابل للإخفاء. إنه framelayout حيث يمكنك تحديد XporterDuffMode والقناع. يمكنك العثور عليها هنا: https://github.com/christophesmet/android_maskable_layout

أنا لست واضحًا تمامًا بشأن ما ستذهب إليه ، لكنني أعتقد أن مزيجًا من BitmapDrawable و LayerDrawable قد تعمل. سيتيح لك BitmapDrawable استخدام نقار الصورة النقطية الخاصة بك كقوالب ، وبعد ذلك يمكنك استخدام Layerdrawlable لطبقة القناع فوق آخر يمكن رسمه.

باستخدام مثال XferModes في عرض API ، تمكنت من استخدام PorterDuffXferMode المطبق على كائن الطلاء لمزج خريطة نصور على قماش. هذا يعمل بالضبط كيف أحتاج إليه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top