项目中需要用到拍摄身份证,拍完照片后直接拿到和身份证比例一致的图片,做成功的结果如下:

  

拍完照后直接拿到裁剪好的图本文的核心技术来自: https://yq.aliyun.com/articles/26706

先看看xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffffff"tools:context="business_android_client.croppercammer.MainActivity"><business_android_client.croppercammer.ClipCameraandroid:id="@+id/surface_view"android:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_gravity="center" /><business_android_client.croppercammer.view.shadowandroid:layout_width="match_parent"android:layout_height="match_parent"/><TextViewandroid:id="@+id/tv_hint"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="请把身份证放入取景框,水平拍摄"android:textColor="#fff"android:rotation="90"android:layout_centerInParent="true"/><Buttonandroid:id="@+id/btn_cancle"android:layout_width="70dp"android:layout_height="70dp"android:background="@drawable/cancle_wite"/><Buttonandroid:layout_alignParentBottom="true"android:id="@+id/btn_shoot"android:layout_width="70dp"android:background="@drawable/sure_wite"android:layout_height="70dp" /></RelativeLayout>

1自定义 shadow extends View 灰色的背景框

   /*** 获取身份证取景框的矩形* @return*/private Rect getShadowRegionRect(){int height = (int) (screenWidth * 0.8);//拍照的阴影框的高度为屏幕宽度的80%  0.8int width = (int) (height * 1.6);//身份证宽高比例为1.6
//        int height= (int) (screenWidth/1.6);int x_center=screenWidth/2;int y_center=screenHeitht/2;
//       return new Rect(0, y_center - (height / 2), screenWidth, height/2 + y_center);return new Rect(x_center-(height/2), y_center - (width / 2), x_center+(height/2), (width/2)+ y_center);}
    @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);
    canvas.clipRect(0, 0, screenWidth, screenHeitht);//画整个屏幕矩形canvas.clipRect(getShadowRegionRect(), Region.Op.DIFFERENCE);//裁剪取景框的矩形canvas.drawColor(0x60000000);canvas.save();canvas.restore();}


2.自定义相机  ClipCamera extends SurfaceView
1获取surfaceHolder
   private void initView() {getScreenMetrix(ctx);holder = getHolder();//获得surfaceHolder引用holder.addCallback(this);holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型}
2 implements SurfaceHolder.Callback 在回调中打开相机,surfaceHolder连接camera,初始化相机
    @Overridepublic void surfaceCreated(SurfaceHolder holder) {if (mCamera == null) {mCamera = Camera.open();//开启相机setCameraParams(mCamera,mScreenWidth,mScreenHeight);try {mCamera.setPreviewDisplay(holder);//摄像头画面显示在Surface上} catch (IOException e) {e.printStackTrace();}}}//初始化相机,主要是选取和屏幕宽高比例最接近的的相机尺寸 ,否则预览图片显示会拉伸
    private void setCameraParams(Camera camera, int width, int height) {Log.i(TAG,"setCameraParams  width="+width+"  height="+height);Camera.Parameters parameters = mCamera.getParameters();// 获取摄像头支持的PictureSize列表List<Camera.Size> pictureSizeList = parameters.getSupportedPictureSizes();for (Camera.Size size : pictureSizeList) {Log.i(TAG, "pictureSizeList size.width=" + size.width + "  size.height=" + size.height);}/**从列表中选取合适的分辨率*/Camera.Size picSize = getProperSize(pictureSizeList, ((float) height / width));if (null == picSize) {Log.i(TAG, "null == picSize");picSize = parameters.getPictureSize();}Log.i(TAG, "picSize.width=" + picSize.width + "  picSize.height=" + picSize.height);// 根据选出的PictureSize重新设置SurfaceView大小float w = picSize.width;float h = picSize.height;parameters.setPictureSize(picSize.width,picSize.height);this.setLayoutParams(new RelativeLayout.LayoutParams((int) (height*(h/w)), height));// 获取摄像头支持的PreviewSize列表List<Camera.Size> previewSizeList = parameters.getSupportedPreviewSizes();for (Camera.Size size : previewSizeList) {Log.i(TAG, "previewSizeList size.width=" + size.width + "  size.height=" + size.height);}Camera.Size preSize = getProperSize(previewSizeList, ((float) height) / width);if (null != preSize) {Log.i(TAG, "preSize.width=" + preSize.width + "  preSize.height=" + preSize.height);parameters.setPreviewSize(preSize.width, preSize.height);}parameters.setJpegQuality(100); // 设置照片质量if (parameters.getSupportedFocusModes().contains(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {parameters.setFocusMode(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 连续对焦模式}mCamera.cancelAutoFocus();//自动对焦。mCamera.setDisplayOrientation(90);// 设置PreviewDisplay的方向,效果就是将捕获的画面旋转多少度显示mCamera.setParameters(parameters);}


3拍照,裁剪
裁剪图片只有一行核心代码 bm= Bitmap.creatBitmap(x,y,width,height)
x:拍完图片的x轴中心
y:拍完整图片的y轴中心
height:身份证宽,(因为在图片预览时旋转了90度)阴影框的宽,阴影宽度为屏幕的80%,同样也是照片宽度的80%,因为取景框在屏幕的中间
width:身份证高,身份证宽高比为1.6有了宽后乘以1.6就可以了
参数 String savePath; public void takePicture(String savePath){ this.savePath=savePath; //设置参数,并拍照 setCameraParams(mCamera, mScreenWidth, mScreenHeight); // 当调用camera.takePiture方法后,camera关闭了预览,这时需要调用startPreview()来重新开启预览
mCamera.takePicture(null, null, jpeg);//参数1:按下快门时的回调
                     2拍照回调,未压缩数据的回调
                      3拍照回调,jpeg照片数据回调
 } //创建jpeg图片回调数据对象 private Camera.PictureCallback jpeg = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera Camera) { BufferedOutputStream bos = null;
Bitmap bm = null; try { // 获得图片 bm = BitmapFactory.decodeByteArray(data, 0, data.length); int pic_width = bm.getWidth();//原始图片的宽 int pic_height= bm.getHeight();//原始图片的高
int height,width,x_center,y_center; height = (int) (pic_height * 0.8);//截取图片的高 屏幕宽的0.8,拍照取景框的宽为屏幕的0.8 width = (int) (height * 1.6);//截取图片的宽 x_center=pic_width/2;//原始图片x中心 y_center=pic_height/2;//原始图片y轴中心 Matrix matrix = new Matrix(); matrix.postRotate(360,pic_width/2,pic_height/2);
bm = Bitmap.createBitmap(bm, x_center - (width / 2) ,//裁剪图片 y_center - (height / 2) , (int) (pic_height*0.8*1.6), (int) (pic_height*0.8), matrix,false); if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Log.i(TAG, "Environment.getExternalStorageDirectory()="+Environment.getExternalStorageDirectory());
// String filePath = "/sdcard/dyk"+System.currentTimeMillis()+".jpg";//照片保存路径 File file = new File(savePath); if (!file.exists()){ file.createNewFile(); } bos = new BufferedOutputStream(new FileOutputStream(file)); bm.compress(Bitmap.CompressFormat.JPEG, 100,
bos);//将图片压缩到流中 }else{ Toast.makeText(ctx,"没有检测到内存卡", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { e.printStackTrace(); } finally { try { bos.flush();//输出 bos.close();//关闭 bm.recycle();// 回收bitmap空间 mCamera.stopPreview();// 关闭预览 Uri uri = Uri.fromFile(new
File(savePath)); Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(uri); ctx.sendBroadcast(intent); ctx.startActivity(intent.setClass(ctx,PreView.class)); } catch (IOException e) { e.printStackTrace(); } } } };


完整的项目下载地址:   https://github.com/tianyalian/CropperCammer.git





												

Android 自定义相机 身份证拍照 自定义身份证相机相关推荐

  1. Android Studio:使用Camera拍照(三)为相机增加取景蒙板/浮层

    写在前面的话:每一个实例的代码都会附上相应的代码片或者图片,保证代码完整展示在博客中.最重要的是保证例程的完整性!!!方便自己也方便他人~欢迎大家交流讨论~本文为博主原创文章,未经博主允许不得转载. ...

  2. 多目相机同步拍照四目相机同步拍照设计方案(多个SENSOR+FPGA+DDR+千兆网)

    绪论 在某些应用场景,需要使用多个相机完全同步进行拍摄,拍摄的开始时间和结束时间完全同步.要达到这样的要求,市面上的大部分通用相机无法达到这样的要求.通用的做法可以带触发的工业相机来实现.具体的实现方 ...

  3. 安卓调用系统相机进行拍照

    安卓调用系统相机进行拍照 调用系统相机进行拍照的话,步骤比较简单,分为两步 使用隐式Intent打开相机 在onActivityResult回调中对图片进行处理 (传回来的图片分为缩略图和原图,缩略图 ...

  4. Android 拍身份证(自定义相机)

    Android自定义相机拍摄二代身份证. 感谢开源,尊重他人劳动成果,本自定义相机拍照核心逻辑取自云栖社区上Android 手把手带你玩转自定义相机 文章,本文仅仅在此基础上再次封装了返回拍照地址等监 ...

  5. 安卓 自定义相机,身份证拍照

    最近项目需要实现身份证拍照的功能,系统的相机并不能满足需求,故需要自定义相机,先上效果图,使用了Camera+ SurfaceView; 布局文件 <?xml version="1.0 ...

  6. uniapp 微信小程序 - 调起手机摄像头: 拍摄身份证的正反面,自定义身份证取景框,在相机上绘制 “身份证轮廓“ 与提示文字(超详细示例源码,一键复制运行开箱即用)

    效果图 这个需求很难在网上找到,就算找到都是很乱的代码.. 本篇博客实现了在uniapp项目中,微信小程序平台下调起手机相机照身份证功能,在相机上添加辅助框.自定义文案或图片(给相机加上身份证辅助线的 ...

  7. 如何用uniapp+vue开发自定义相机插件——拍照+录像功能

    调用手机的相机功能并实现拍照和录像是很多APP与插件都必不可少的一个功能,今天智密科技就来分享一下如何基于uniapp + vue实现自定义相机界面,并且实现: 1: 自定义拍照 2: 自定义录像 3 ...

  8. android之利用surfaceView实现自定义水印相机

    android之利用surfaceView实现自定义水印相机 知识点 1.自定义相机+预览相机 2.截屏拍照加水印 3.关于不使用intent来传输图片 4.关于大家说要demo的,因为这里是项目里头 ...

  9. uniapp小程序开发自定义相机、拍照、上传

    功能背景 项目开发小程序,想要实现一个自定义相机的功能,需要可以拍照,并且显示经纬度等一些其他信息在相机画面上.而且拍照上传,是可以将文字叠加在图片上(目前我这里是由后端实现的,前端应该也是可以做的, ...

最新文章

  1. python包括哪些部分_python基础知识部分练习大全
  2. C++coin change 硬币找零(附完整源码)
  3. git中使用fork
  4. javascript查找关键字高亮效果
  5. Python3爬虫入门之pyquery库的使用
  6. 计算机开题报告中的研究方法,开题报告:经济学写论文用到的五种研究方法
  7. 最小树——迪杰斯特拉算法
  8. 使用 SpringBoot 写 RESTful风格 增删改查接口
  9. 世界上主要BIOS厂家介绍(Phoenix,AMI,Insyde,Byosoft)
  10. Python html.parser库学习小结
  11. 直入樱花深处,静待落英满襟
  12. html中微博发布怎么做,js实现微博发布小功能
  13. C#不能直接打开 wod文档,只能保存到本地再打开
  14. linux磁盘挂载方式mount
  15. python怎么多行输入_python如何输入多行
  16. My97DatePicker时间控件
  17. IPSEC ×××连连看
  18. Booktrack Cla***oom(有声电子书)
  19. linux网络显示不出来ens33,如何解决Linux 系统下 ifconfig 命令无网络接口 ens33
  20. vuejs中如何实现三级路由并刷新页面时保持当前路由激活状态

热门文章

  1. 笔记本html外接显示器,笔记本怎样外接显示器 笔记本外接显示器方法【详解】...
  2. Html —— 获取输入框input的值
  3. 小程序为什么要办理ICP许可证
  4. 口袋理财:“来了就是深圳人?”全国均价最高的房租了解一下
  5. 机房装饰实施方案的评审
  6. 软件工程毕业论文mysql英文翻译,软件工程专业毕业设计外文文献翻译.doc
  7. 备案域名服务器DNS修改,未备案域名也可以用高防CDN加速
  8. 温莎大学应用计算机,加拿大留学,温莎大学英语计算机专业了解一下
  9. js实现任意节日倒计时html
  10. lopa分析_保护层分析(LOPA)