需求
我们之前做了一款拍照APP,现在需要在拍摄的时候,提供一个人脸提示框(因为我们最后不是保留所有的图像,而是仅保留中间一部分图像)
思路
在预览图层前,再添加一层画布,在新的画布上绘制人脸框和矩形框。也就是说,实际上我们仅仅是在预览的镜头前添加,而非对相机做什么修改。
具体步骤
步骤一:添加新图层
使用FrameLayout(下方的内容会覆盖在上方的内容上),在我们的预览用SurfaceView之上添加一个自定义画布
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<SurfaceView
android:id="@+id/cameraSV"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="visible" />
<com.example.matting.SVDraw
android:id="@+id/drawIV"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout>
步骤二:自定义画布设置
public class SVDraw extends SurfaceView implements Callback{
protected SurfaceHolder sh;
private String TestTag = "TestLog";
public SVDraw(Context context, AttributeSet attrs) {
super(context, attrs);
sh = getHolder();
sh.addCallback(this);
sh.setFormat(PixelFormat.TRANSPARENT); // 设置透明
setZOrderOnTop(true); // 置顶
}
/*
...其他的一些函数
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
步骤三:在画布上绘制矩形框及人脸框
使用函数的形式,方便外部调用
public synchronized void drawRect() {
Canvas canvas = sh.lockCanvas();
canvas.drawColor(Color.TRANSPARENT);
// 红色提示矩形框画笔设置
Paint redPaint = new Paint();
redPaint.setAntiAlias(true);
redPaint.setColor(Color.RED);
redPaint.setStyle(Style.STROKE);
redPaint.setStrokeWidth(4f);
redPaint.setAlpha(100);
// 绿色人物提示框画笔设置
Paint greenPaint = new Paint();
greenPaint.setAntiAlias(true);
greenPaint.setColor(0xFFA4C739);
greenPaint.setStrokeWidth(3.5f);
greenPaint.setStyle(Paint.Style.STROKE);
// 将画布原点移至画布中央(方便画布选点)
canvas.translate(mWidth / 2, mHeight / 2 - 200);
// 绘制外围红色边框
canvas.drawRect(new Rect(-360, -480, 360, 480), redPaint);
// 头部
RectF rectf_head = new RectF(-225, -375, 225, 15);
canvas.drawArc(rectf_head, 200, 140, false, greenPaint);
// 下颌
RectF rectf_mouse = new RectF(-165, 120, 165, 322);
canvas.drawArc(rectf_mouse, 20, 140, false, greenPaint);
// 衬衣
canvas.drawLine(-141, 315, -300, 458, greenPaint);
canvas.drawLine(141, 315, 300, 458, greenPaint);
sh.unlockCanvasAndPost(canvas);
}
分为两部分,一部分红色画笔,绘制的是最终的裁剪区域外轮廓。一部分是分步的人脸绘制。也许可以采用贴图的方法整体实现,但是由于我没有半透明的矢量图可用,所以用蠢方法实现了。
步骤四:清屏函数
由于我们的人脸框是可以随时收回的,所以要添加一个函数,用于将绘制的图案隐藏,实际上我们是将绘制的图案直接清除,以此实现取消辅助线
void clearDraw() {
Canvas canvas = sh.lockCanvas();
canvas.drawColor(Color.BLUE);
sh.unlockCanvasAndPost(canvas);
}
步骤五:声明属性
private SVDraw myDraw = null;
步骤六:onCreate中初始化第二层屏幕
// 初始化画板
myDraw = (SVDraw) findViewById(R.id.drawIV);
步骤七:添加函数调用
当需要添加辅助线的时候(比如说点击了添加按钮),调用相应的函数即可
myDraw.drawRect();
效果展示
提示框效果展示灰色区域是预览区域,点击绘制后会显示红色提示框和绿色人脸框
完整代码
完整代码请移步github项目Github项目:《Matting》 By ZaoZhe6666
在camera.xml中是相机的相关布局。
在SVDraw.java中是本文提到的设置画布的绘制部分。
在UseCameraActivity中是本文对画布绘制功能(辅助线添加功能)的具体使用。
网友评论