Android 自定义相机 身份证拍照 自定义身份证相机 - Go语言中文社区

Android 自定义相机 身份证拍照 自定义身份证相机


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

  

拍完照后直接拿到裁剪好的图本文的核心技术来自: 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.ClipCamera
        android:id="@+id/surface_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_gravity="center" />

    <business_android_client.croppercammer.view.shadow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />


    <TextView
        android: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"
        />

    <Button
        android:id="@+id/btn_cancle"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:background="@drawable/cancle_wite"
        />

    <Button
        android: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.8
       int 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);

    }
    @Override
    protected 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,初始化相机

    @Override
    public 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







版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_35599978/article/details/72729794
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-26 21:29:00
  • 阅读 ( 599 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢