画布上的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
}
})
}
}