检测Android设备是否支持照相机
/**
* 检测设备是否支持相机
*
* @param context
* @return
*/
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
}
return false;
}
定制拍照程序的步骤:
1、打开相机:Camera.open();
2、创建SurfaceView对象;
3、添加回调监听器(SurfaceHolder.Callback);
4、预览(mCamera.startPreview);
5、拍照(mCamera.takePicture);
网上资料:
网上写的挺详细的具体自定义操作请查阅以下资料:
Android 自定义Camera相机
https://blog.csdn.net/qq_38001118/article/details/81871564
Android: Camera相机开发详解(上) —— 知识储备
https://www.jianshu.com/p/f8d0d1467584
Android: Camera相机开发详解(中) ——实现预览、拍照、保存照片等功能
https://www.jianshu.com/p/e20a2ad6ad9a
Android: Camera相机开发详解(下) —— 实现人脸检测功能
https://www.jianshu.com/p/3bb301c302e8
Android:Camera2开发详解(上):实现预览、拍照、保存照片等功能
https://www.jianshu.com/p/0ea5e201260f
项目中遇到的问题:
魔镜项目中人脸识别需要一个宽高为630x780px的框而相机中给的预览和图片尺寸没有给定与项目接近的值
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-0: width:1280--height:720
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-1: width:1920--height:1080
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-2: width:208--height:144
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-3: width:176--height:144
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-4: width:352--height:288
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-5: width:320--height:240
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-6: width:480--height:320
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-7: width:640--height:480
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-8: width:800--height:480
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-9: width:960--height:544
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-10: width:960--height:720
07-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-11: width:720--height:720
07-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-0: width:320--height:240
07-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-1: width:640--height:480
07-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-2: width:1280--height:720
07-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-3: width:1920--height:1080
07-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-4: width:2432--height:2432
07-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-5: width:3264--height:2448
07-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-6: width:4160--height:2336
07-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-7: width:5152--height:2896
07-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-8: width:5152--height:3888
解决思路:
1、我们设置图片尺寸和预览尺寸为1920x1080px;
2、在布局中添加一个同样大小位置的蒙层,其中中间通过计算留出630x780px;
3、对拍照的图片通过位置计算进行截取;
1、我们设置图片尺寸和预览尺寸为1920x1080px;
parameters.setPreviewSize(1920, 1080);
parameters.setPictureSize(1920, 1080);
2、在布局中添加一个同样大小位置的蒙层,其中中间通过计算留出630x780px;
package com.yx.mirror.third.camera.view;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.yx.mirror.R;
/**
* Description 遮挡的View
*
* @author hzy
* Create on 2019/7/23 10:13
*/
public class OcclusionView extends View {
private Paint mPaint;
private int mMaskColor; // 取景框外的背景颜色
private int mCameraWidth;
private int mCameraHeight;
private int mPicWidth;
private int mPicHeight;
/**
* 中点距离和marginTop的差值,由于横向是居中,所以不用计算
*/
private int marginDifference;
private OcclusionView mOcclusionView;
public OcclusionView(Context context) {
super(context);
initView();
}
public OcclusionView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView();
}
private void initView() {
Resources resources = getResources();
mMaskColor = resources.getColor(R.color.black_back);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 绘制取景框外的暗灰色的表面,分四个矩形绘制
mPaint.setColor(mMaskColor);
}
public void setOcclusionView(OcclusionView mOcclusionView, int mCameraWidth, int mCameraHeight, int mPicWidth, int mPicHeight, int marginDifference) {
this.mOcclusionView = mOcclusionView;
this.mCameraWidth = mCameraWidth;
this.mCameraHeight = mCameraHeight;
this.mPicWidth = mPicWidth;
this.mPicHeight = mPicHeight;
this.marginDifference = marginDifference;
}
@Override
public void onDraw(Canvas canvas) {
if (mOcclusionView == null) {
return; // not ready yet, early draw before done configuring
}
// 黑色区域
Path path1 = new Path();
path1.addRect(new RectF(0, 0, mCameraWidth, mCameraHeight), Path.Direction.CW);
//透明区域
Path path2 = new Path();
path2.addRect(new RectF((mCameraWidth - mPicWidth) / 2, (mCameraHeight - mPicHeight) / 2 + marginDifference, (mCameraWidth + mPicWidth) / 2, (mCameraHeight + mPicHeight) / 2 + marginDifference), Path.Direction.CW);
//DIFFERENCE,path1减去path1和path2相交部分
path1.op(path2, Path.Op.DIFFERENCE);
canvas.drawPath(path1, mPaint);
}
}
3、对拍照的图片通过位置计算进行截取;
/**
* 人脸照片处理
*
* @param bmp
*/
private void showFragment(Bitmap bmp) {
translateAnimation.cancel();//动画取消
mImvLine.setVisibility(View.GONE);
Matrix matrix = new Matrix();
//镜子效果
matrix.setScale(-1, 1);
matrix.postTranslate(bmp.getWidth(), 0);
//旋转图片
Bitmap rotateBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
//截图至当前图片的大小
Bitmap bitmap = cropBitmap(rotateBitmap, 630, 780);
photoPath = "/qimg/report/" + DateUtil.getDateYmd() + "/" + System.currentTimeMillis() + ".png";
writeBitmapToFile(bitmap, photoPath);
mCameraContainer.setVisibility(View.GONE);
mPhotoIv.setImageBitmap(bitmap);
mPhotoIv.setVisibility(View.VISIBLE);
postImg(bitmap);
}
/**
* 裁剪
* https://blog.csdn.net/qunqunstyle99/article/details/87869018
*
* @param bitmap 原图
* @return 裁剪后的图像
*/
private Bitmap cropBitmap(Bitmap bitmap, int picWidth, int picHeight) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int x = 0;
int y = 0;
if (bitmap.getWidth() < picWidth) {
Toast.makeText(this, "x + width must be <= bitmap.width()", Toast.LENGTH_SHORT).show();
return bitmap;
}
if (bitmap.getHeight() < picHeight) {
Toast.makeText(this, "y + height must be <= bitmap.height()", Toast.LENGTH_SHORT).show();
return bitmap;
}
x = (w - picWidth) / 2;
y = (h - picHeight) / 2;
return Bitmap.createBitmap(bitmap, x, y, picWidth, picHeight, null, false);
}