画布上的Android Mask位图生成黑色空间

时间:2014-05-31 04:05:54

标签: android bitmap mask

我有一个掩码位图,其中一半是红色,一个是透明的 https://www.dropbox.com/s/931ixef6myzusi0/s_2.png

我想使用蒙版位图在画布上绘制内容,只能在红色区域中看到,代码如下:

Paint paint = new Paint();


public void draw(Canvas canvas) {
// draw content here
  ...

//and mask bitmap here
  paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.DST_IN));
  canvas.drawBitmap(maskBitmap, 0, 0, paint);

}

我期待的结果(内容仅在红色区域可见,但透明区域成为黑色是问题!)

此图片结果:https://www.dropbox.com/s/mqj48992wllfkiq/s_2%20copy.png 有人帮我???

5 个答案:

答案 0 :(得分:34)

这是一个帮助我实现屏蔽的解决方案:

public void draw(Canvas canvas) {
        Bitmap original = BitmapFactory.decodeResource(getContext().getResources(),R.drawable.original_image);
        Bitmap mask = BitmapFactory.decodeResource(getContext().getResources(),R.drawable.mask_image);

        //You can change original image here and draw anything you want to be masked on it.

        Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Config.ARGB_8888);
        Canvas tempCanvas = new Canvas(result);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
        tempCanvas.drawBitmap(original, 0, 0, null);
        tempCanvas.drawBitmap(mask, 0, 0, paint);
        paint.setXfermode(null);

        //Draw result after performing masking
        canvas.drawBitmap(result, 0, 0, new Paint());
}

面具应该是具有透明度的白色图像。
它会像这样工作:
original image + mask = result image

答案 1 :(得分:6)

我在自定义视图中遇到了同样的问题,而不是从资源解码位图,我通过canvas.draw*()方法从头开始创建了原始位图和掩码位图(因为原始和掩码都是基本形状)。我得到blank opaque space而不是transparent。我通过在我的视图中设置硬件层来修复它。

View.setLayerType(LAYER_TYPE_HARDWARE, paint);

有关为何要在此处执行此操作的详细信息:https://stackoverflow.com/a/33483016/4747587

答案 2 :(得分:0)

Bitmap finalMasking = stackMaskingProcess(imageBitmap, bitmapMasking);


private Bitmap stackMaskingProcess(Bitmap _originalBitmap, Bitmap _maskingBitmap) {
        try {
            if (_originalBitmap != null)
            {
                int intWidth = _originalBitmap.getWidth();
                int intHeight = _originalBitmap.getHeight();
                resultMaskBitmap = Bitmap.createBitmap(intWidth, intHeight, Bitmap.Config.ARGB_8888);
                getMaskBitmap = Bitmap.createScaledBitmap(_maskingBitmap, intWidth, intHeight, true);
                Canvas mCanvas = new Canvas(resultMaskBitmap);
                Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
                mCanvas.drawBitmap(_originalBitmap, 0, 0, null);
                mCanvas.drawBitmap(getMaskBitmap, 0, 0, paint);
                paint.setXfermode(null);
                paint.setStyle(Paint.Style.STROKE);
            }
        } catch (OutOfMemoryError o) {
            o.printStackTrace();
        }
        return resultMaskBitmap;
    }

答案 3 :(得分:0)

我喜欢Er. Praful Parmar's回答中的方法,但对我来说,它的效果并不理想。我遇到了问题,因为某些扩展一直在无意间进行。
我的位图的密度不同于设备的密度,这使事情搞砸了。

我还想减少对象的创建,所以我将Paint对象移动到一个常量以供重用。

这是我的utils方法:

  public static final//
  Bitmap createWithMask(final Bitmap img, final Bitmap mask) {
    final Bitmap result = Bitmap.createBitmap(img.getWidth(), img.getHeight(),
        Bitmap.Config.ARGB_8888);
    result.setDensity(originalBitmap.getDensity()); // to avoid scaling if density of 'img' is different form the default on your device
    final Canvas canvas = new Canvas(result);
    canvas.drawBitmap(img, 0, 0, null);
    canvas.drawBitmap(mask, 0, 0, PAINT_FOR_MASK);
    return result;
  }//end-method

  private static final Paint PAINT_FOR_MASK = createPaintForMask();

  private static final//
  Paint createPaintForMask() {
    final Paint paint = new Paint();
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    return paint;
  }//end-method

答案 4 :(得分:0)

<块引用>

与@Sergey Pekar 给出的答案相同,但我已在 Kotlin 中对其进行了更新。

enter image description here

fun ImageView.getMaskBitmap(imageUrl: String? = null, mContent: Int, mMaskedImage : Int) {
    runOnBackground {
        // if you have https image url then use below line
        //val original: Bitmap = BitmapFactory.decodeStream(URL(imageUrl).openConnection().getInputStream())

        // if you have png or jpg image then use below line
        val original: Bitmap = BitmapFactory.decodeResource(resources, mContent)

        val mask = BitmapFactory.decodeResource(resources, mMaskedImage) // mMaskedImage Your masking image
        val result: Bitmap = Bitmap.createBitmap(mask.width, mask.height, Bitmap.Config.ARGB_8888, true)
        val tempCanvas = Canvas(result)
        val paint = Paint(Paint.ANTI_ALIAS_FLAG)
        paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
        tempCanvas.apply {
            drawBitmap(original, 0f, 0f, null)
            drawBitmap(mask, 0f, 0f, paint)
        }
        paint.xfermode = null

        //Draw result after performing masking
        runOnBackground(onMainThread = {
            this.apply {
                setImageBitmap(result)
                scaleType = ImageView.ScaleType.FIT_CENTER
            }
        })
    }
}

Github Demo