2010-04-12 17 views
17

मैं वर्तमान में किसी अन्य बिटमैप के अल्फा चैनल या एंड्रॉइड पर ड्रायबल को मास्क करने के लिए एक काले और सफेद बिटमैप का उपयोग करने का एक तरीका ढूंढ रहा हूं। मैं उत्सुक हूं कि ऐसा करने का सबसे अच्छा तरीका क्या है। मेरे पास निश्चित रूप से कुछ विचार हैं कि यह कैसे करें, लेकिन वे इष्टतम नहीं हैं।एंड्रॉइड पर एक ड्रायरेबल/बिटमैप मास्किंग

मुझे छवि में हर बार एक नया मुखौटा लागू करने में सक्षम होना चाहिए (काला और सफेद बिटमैप हर कुछ सेकंड में बदल जाएगा)।

इसे प्राप्त करने के तरीके पर कोई प्रतिक्रिया बहुत सराहना की जाएगी।

+0

मैं अन्य बिटमैप/ड्रायबल पर संबंधित पिक्सेल के अल्फा चैनल को सेट करने के लिए मास्क बिटमैप के काले हिस्सों का उपयोग करने की कोशिश कर रहा हूं। –

उत्तर

3

मैं यह काम कर रहा है, तो यह इस

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

यदि 'super.draw (कैनवास)' के बजाय, ड्रा विधि को ओवरराइड करना 'super.onDraw (कैनवास) 'होना चाहिए। अन्यथा आप StackOverflow त्रुटि के साथ अंतहीन पाश में समाप्त हो जाते हैं। – Speedy

+0

मैंने अपने कस्टम व्यू के 'ऑनड्रा' में उपर्युक्त जैसा ही किया, लेकिन ऐसा लगता है कि 'saveLayer' महंगा है और इसलिए इसके बजाय मैंने अपने दृश्य में हार्डवेयर परत सेट की है ('View.setLayerType (LAYER_TYPE_HARDWARE, पेंट) ')। अधिक जानकारी: http://stackoverflow.com/a/33483016/4747587 – Henry

2

मैं जो कुछ भी कर रहा हूं उस पर पूरी तरह से स्पष्ट नहीं हूं, लेकिन मेरा मानना ​​है कि BitmapDrawable और LayerDrawable का संयोजन काम कर सकता है। बिटमैप ड्रावेबल आपको अपने बिटमैप्स को ड्रॉबल्स के रूप में उपयोग करने की अनुमति देगा, और फिर आप लेयर ड्रावेबल का उपयोग किसी अन्य ड्रायरेबल के शीर्ष पर मास्क को लेयर करने के लिए कर सकते हैं।

+0

मैं इसे देख लूंगा, धन्यवाद। –

1

एपीआई डेमो में एक्सफर्मोड उदाहरण का उपयोग करके मैं कैनवास पर दो बिटमैप्स को एक साथ मिश्रित करने के लिए एक पेंट ऑब्जेक्ट पर लागू एक पोर्टरडफैक्सफर्मोड का उपयोग करने में सक्षम था। यह वास्तव में काम करता है कि मुझे इसकी आवश्यकता कैसे है।

+12

क्या आप अधिक जानकारी जोड़ सकते हैं? – Casebash

3

मैं एक maskable लेआउट बनाया की तरह कुछ है। यह एक framelayout है जहां आप xporterduffmode और मुखौटा निर्दिष्ट कर सकते हैं। आप इसे यहां पा सकते हैं: https://github.com/christophesmet/android_maskable_layout

5

मेरा समाधान @ 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>); 

फिर आखिरकार, ऑनड्रा() विधि मास्क पर लागू होती है:

@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 को संदर्भित किया। वह पृष्ठ पढ़ने के लिए बहुत दिलचस्प है। उसके बाद, उसी तरह के कोड के साथ आप एक साधारण मुखौटा से ज्यादा प्राप्त करने में सक्षम होंगे!

+0

बिल्कुल सही समाधान। दूसरों को थोड़ा लंबा है। – Jona

+0

स्वीकृत उत्तर से बेहतर आईएमओ, मैं पथ पर आकर्षित करने योग्य पसंद करता हूं –

संबंधित मुद्दे