2010-04-12 4 views
17

현재 안드로이드에서 흑백 비트 맵을 사용하여 다른 비트 맵 또는 드로어 블의 알파 채널을 마스킹하는 방법을 찾고 있습니다. 이 일을하는 가장 좋은 방법은 무엇인지 궁금합니다. 나는 확실히 이것을하는 방법에 대한 몇 가지 아이디어가 있지만 최적이 아닙니다.안드로이드에서 드로어 블/비트 맵 마스킹

매번 이미지에 새 마스크를 적용 할 수 있어야합니다 (흑백 비트 맵은 몇 초마다 변경됩니다).

이 문제를 해결하는 방법에 대한 피드백은 크게 감사하겠습니다.

+0

마스크 비트 맵의 ​​검은 부분을 사용하여 다른 비트 맵/드로어 블에있는 해당 픽셀의 알파 채널을 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

onDraw 메서드를 오버라이드하는 경우,'super.draw (canvas)'대신'super.onDraw (canvas)'가 있어야합니다. 그렇지 않으면 끝없는 루프에서 StackOverflow 오류가 발생합니다. – Speedy

+0

커스텀 뷰의'onDraw'에서 위와 같은 일을했지만 saveLayer는 비싸고 대신 뷰에 하드웨어 레이어를 설정합니다 ('View.setLayerType (LAYER_TYPE_HARDWARE, paint) '). 자세한 정보 : http://stackoverflow.com/a/33483016/4747587 – Henry

2

나는 당신이 무엇을할지는 분명하지 않지만, BitmapDrawableLayerDrawable의 조합이 효과가있을 것이라고 생각합니다. BitmapDrawable을 사용하면 비트 맵을 드로어 블로 사용하고 LayerDrawable을 사용하여 다른 드로어 블 위에 마스크를 레이어 할 수 있습니다.

+0

감사합니다. –

1

API 데모에서 Xfermodes 예제를 사용하면 Paint 객체에 적용된 PorterDuffXfermode를 사용하여 캔버스에 두 비트 맵을 혼합 할 수있었습니다. 이것은 정확히 내가 필요로하는 방식으로 작동합니다.

+12

자세한 내용을 추가 할 수 있습니까? – Casebash

5

내 솔루션은 @ over_optimistic의 솔루션에 가까울수록 saveLayer() 호출이 적습니다. 필자는 경로 대신 Drawable 마스크를 사용합니다. 제 경우에는 디스크였습니다. 어딘가의 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을 참조했다. 그 페이지는 꽤 재미 있습니다. 그런 다음 동일한 종류의 코드를 사용하면 간단한 마스크보다 훨씬 더 많은 것을 습득 할 수 있습니다!

+0

완벽한 솔루션. 다른 것들은 너무 길다. – Jona

+0

허용되는 답변보다 IMO가 우수하며 경로를 통해 드로어 블을 선호합니다. –

관련 문제