Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
画布上的Android掩码位图生成一个黑色空间_Android_Bitmap_Mask - Fatal编程技术网

画布上的Android掩码位图生成一个黑色空间

画布上的Android掩码位图生成一个黑色空间,android,bitmap,mask,Android,Bitmap,Mask,我有一个遮罩位图,一半是红色,另一半是透明的 我想使用遮罩位图在画布上绘制仅在红色区域可见的内容,代码如下: 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_

我有一个遮罩位图,一半是红色,另一半是透明的

我想使用遮罩位图在画布上绘制仅在红色区域可见的内容,代码如下:

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

}
结果如我所料(内容仅在红色区域可见,但透明区域变为黑色是问题!)

此图像结果:
有人帮我吗?

这里有一个解决方案帮助我实现掩蔽:

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());
}
遮罩应该是透明的白色图像。
它的工作原理如下:

+=

我在自定义视图中遇到了相同的问题,我没有从资源中解码位图,而是通过
canvas.draw*()
方法从头创建了原始位图和遮罩位图(因为原始和遮罩都是基本形状)。我得到的是
空白不透明空间
,而不是
透明的
空间。我通过在视图中设置硬件层来修复它

View.setLayerType(LAYER_TYPE_HARDWARE, paint);
更多关于为什么要在这里这样做的信息:

我喜欢答案中的方法,但对我来说,它并没有像预期的那样有效。我遇到了一些问题,因为一些缩放是在无意中进行的。
我的位图的密度与我的设备不同,这把事情搞砸了

我还想减少对象的创建,所以我将
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
与@Sergey Pekar give的答案相同,但我已在Kotlin中对其进行了更新


这将非常缓慢,因为屏幕外画布不是硬件加速器。我发现,即使使用OpenGL,画布图形仍然非常必要,因为它可以动态生成图形,稍后可以加载到OpenGL着色器。也就是说,这仍然非常有用。但是在onDraw()中创建位图可能会导致内存不足异常,正如您所提到的,它不应为白色。透明通道就足够了。检查在draw参数中传递的内容
  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
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
            }
        })
    }
}