我正在尝试在Android上的视频供稿(预览)中应用蒙版。
我们的想法是在设备屏幕上裁剪视频,使其看起来像圆形。
这是我迄今为止所取得的成就:
(忽略视频Feed中的黑色圆形条带,即xml布局中的单独资源)
正如你所看到的,我有视频,中间有一个圆孔。我需要相反(即我应该在“洞”内看到视频,其余部分应该是不可见的。)
我正在覆盖我的SurfaceView的绘制方法并应用Porter-Duff模式:
以下是相关代码:
package org.dornad.test;
import android.content.Context;
import android.graphics.*;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private Camera camera;
private final SurfaceHolder holder;
private Bitmap rounderBitmap;
private Paint xferPaint;
public CameraPreview(Context context, Camera camera) {
super(context);
this.camera = camera;
holder = getHolder();
holder.addCallback(this);
this.setDrawingCacheEnabled(true);
}
@Override
public void draw(Canvas canvas) {
Bitmap currentBitmap = get();
int w = currentBitmap.getWidth(), h = currentBitmap.getHeight();
if (rounderBitmap == null)
rounderBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(rounderBitmap);
if (xferPaint == null)
xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
xferPaint.setColor(Color.RED);
c.drawCircle(w/2, h/2, 100, xferPaint);
xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(currentBitmap, 0, 0, null);
canvas.drawBitmap(rounderBitmap, 0, 0, xferPaint);
}
private Bitmap get() {
return this.getDrawingCache();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
setWillNotDraw(false);
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (IOException e) {
L.d("Error setting camera preview : %s", e.getMessage());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (holder.getSurface() == null) {
return;
}
try {
camera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop an non-existent preview
}
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (IOException e) {
L.d("Error setting camera preview : %s", e.getMessage());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in the Activity/Fragment.
}
}
根据Porter-Duff混合模式的视觉指南:
我正在寻找的应该是PorterDuff.Mode.XOR,但我得到的是带有红色填充的圆圈,而不是视频源。 (我知道红色来自xferPaint.setColor调用)
有什么想法吗?
答案 0 :(得分:0)
您正在使用xferPaint
来做两件事:
并且您正在使用rounderBitmap
将每个渲染中的圆圈重新绘制到DST_IN
中!
我认为如果您重新排序代码,您可能会得到想要的结果(未经测试):
Bitmap currentBitmap = get();
int w = currentBitmap.getWidth(), h = currentBitmap.getHeight();
if (rounderBitmap == null) {
rounderBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(rounderBitmap);
Paint holePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
holePaint.setColor(Color.RED);
c.drawCircle(w / 2, h / 2, 100, holePaint);
}
if (xferPaint == null) {
Paint xferPaint = new Paint();
xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
}
canvas.drawBitmap(currentBitmap, 0, 0, null);
canvas.drawBitmap(rounderBitmap, 0, 0, xferPaint);
如果它有效,那么您可能需要考虑:
rounderBitmap
分配为200x200
位图,而不是w x h
drawCircle(100, 100, 100
rounderBitmap
位置w/2-100
,h/2-100
时drawBitmap
位置。一般情况下,您可以尝试转储位图以查看它是否是您想要的位置(图像中间有一个圆圈(正确的颜色/ alpha):
static int counter;
// inside draw:
File out = new File(getContext().getExternalCacheDir(), "frame_"+ counter++ +".png");
Bitmap.compress(Bitmap.CompressFormat.PNG, 0, new FileOutputStream(out));
Log.d("DEBUG", "Written: " + out);
免责声明:我没有使用PorterDuff的经验,以上所有内容只是一般建议。