Android 自定义相机
16lz
2021-01-23
检测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:72007-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-1: width:1920--height:108007-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-2: width:208--height:14407-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-3: width:176--height:14407-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-4: width:352--height:28807-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-5: width:320--height:24007-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-6: width:480--height:32007-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-7: width:640--height:48007-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-8: width:800--height:48007-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-9: width:960--height:54407-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-10: width:960--height:72007-19 17:29:58.280 24520-24520/com.hzy.exampledemo D/mPreviewSizes-11: width:720--height:72007-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-0: width:320--height:24007-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-1: width:640--height:48007-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-2: width:1280--height:72007-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-3: width:1920--height:108007-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-4: width:2432--height:243207-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-5: width:3264--height:244807-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-6: width:4160--height:233607-19 17:36:17.400 24520-24520/com.hzy.exampledemo D/mPictureSizes-7: width:5152--height:289607-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); }
更多相关文章
- Android 通过经纬度获取地理位置信息
- Android Animation动画详解
- [置顶] android调用系统相机拍照并保存在本地
- android P虚拟按键点击位置加大的问题
- Android 定位自己当前位置信息
- Android调用相机相册并显示照片在ImageView