Android扫描名片的动画以及剪裁扫描框的图片

2024-09-07 12:48

本文主要是介绍Android扫描名片的动画以及剪裁扫描框的图片,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考代码:https://github.com/smartown/CertificateCamera

本文章在上述参考代码的基础上进行修改,用到的SurfaceView是链接代码里的CameraPreview,不过本人比较懒,直接加入相机连续对焦模式代替点击屏幕对焦   ,在CameraPreview中添加

parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 连续对焦模式

即可。

布局文件:

主要是用半透明的view将中间的扫描框包围其起来

代码如下:

<?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="#000"><com.view.CameraPreviewandroid:id="@+id/camera_surface"android:layout_width="match_parent"android:layout_height="match_parent" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:orientation="vertical"><Viewandroid:id="@+id/viewtop"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="@color/preview_mock" /><!--android:background="#5e9" />--><!--android:background="@color/preview_mock" />--><LinearLayoutandroid:id="@+id/camera_crop_container"android:layout_width="0dp"android:layout_height="0dp"android:orientation="horizontal"><Viewandroid:id="@+id/viewleft"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@color/preview_mock" /><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"><ImageViewandroid:id="@+id/camera_crop"android:layout_width="0dp"android:layout_height="0dp"android:scaleType="fitXY" /><ImageViewandroid:id="@+id/iv_scan_line"android:layout_width="200dp"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_centerHorizontal="true"android:maxHeight="250dp"android:src="@mipmap/face_scan_line"android:visibility="gone"/></RelativeLayout><RelativeLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@color/preview_mock"><Viewandroid:id="@+id/viewright"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/></RelativeLayout></LinearLayout></LinearLayout><TextViewandroid:id="@+id/tv_picture"android:layout_width="match_parent"android:layout_height="136dp"android:layout_gravity="right"android:gravity="center"android:text="拍照"android:textColor="@color/c_white"android:background="@color/preview_mock"/></LinearLayout><!-- 顶部 --><include layout="@layout/toolbar_right"/><com.view.RotateTextViewandroid:id="@+id/rtv_scaning"android:layout_width="wrap_content"android:layout_height="match_parent"android:textSize="@dimen/sp_14"android:textColor="@color/c_B5B5B5"android:layout_alignParentRight="true"android:gravity="center_vertical"android:layout_centerVertical="true"android:visibility="gone"android:text="识别中"/></RelativeLayout>

在activity中我的改动比较大,由于我只扫描名片不涉及到横屏竖屏切换,所以页面强制竖屏,初始化代码如下,关于权限申请本文章不进行展示了,

private void init() {//获取屏幕最小边,设置为cameraSurface较窄的一边float screenMinSize = Math.min(getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);//根据screenMinSize,计算出cameraSurface的较宽的一边,长宽比为标准的16:9float maxSize = screenMinSize / 9.0f * 16.0f;RelativeLayout.LayoutParams layoutParams;layoutParams = new RelativeLayout.LayoutParams((int) screenMinSize, (int) maxSize);layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);cameraSurface.setLayoutParams(layoutParams);float width = (int) (screenMinSize * 0.65);float height = (int) (width * 43.0f / 30.0f);LinearLayout.LayoutParams containerParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) height);RelativeLayout.LayoutParams cropParams = new RelativeLayout.LayoutParams((int) width, (int) height);containerView.setLayoutParams(containerParams);cropView.setLayoutParams(cropParams);cropView.setImageResource(R.mipmap.face_scan_rect_blue);ivScanLine.setMaxHeight(cropView.getHeight());Display defaultDisplay = getWindowManager().getDefaultDisplay();Point point = new Point();defaultDisplay.getSize(point);int x = point.x;int y = point.y;Log.i(TAG, "x = " + x + ",y = " + y);}

点击拍照后的处理,主要是剪裁与扫描框相同大小的区域:

 cameraSurface.takePhoto(new Camera.PictureCallback() {@Overridepublic void onPictureTaken(final byte[] data, Camera camera) {camera.stopPreview();ivScanLine.setVisibility(View.VISIBLE);rtvScaning.setVisibility(View.VISIBLE);//子线程处理图片,防止ANRnew Thread(new Runnable() {@Overridepublic void run() {try {File originalFile = getOriginalFile();FileOutputStream originalFileOutputStream = new FileOutputStream(originalFile);originalFileOutputStream.write(data);originalFileOutputStream.close();Bitmap bitmap = BitmapFactory.decodeFile(originalFile.getPath());//计算裁剪位置float left, top, right, bottom;left = ((float) containerView.getLeft() - (float) cameraSurface.getLeft()) / (float) cameraSurface.getWidth();top = (float) cropView.getTop() / (float) cameraSurface.getHeight();right = (float) containerView.getRight() / (float) cameraSurface.getWidth();bottom = (float) cropView.getBottom() / (float) cameraSurface.getHeight();//裁剪及保存到文件int w = cropView.getMeasuredWidth();int h = cropView.getMeasuredHeight();cropView.getLocationOnScreen(location);// 获取状态栏高度Rect frame = new Rect();ScanCardActivity.this.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);int statusBarHeight = frame.top;System.out.println(statusBarHeight);Bitmap cropBitmap;//判断照片是横屏还是竖屏if ( bitmap.getWidth()> bitmap.getHeight()){int  lx;if (Utils.checkDeviceHasNavigationBar2(ScanCardActivity.this)){lx =viewtop.getHeight()-statusBarHeight+NavUtils.getNavigationBarHeight(ScanCardActivity.this);}else{lx=viewtop.getHeight()-statusBarHeight;}int   ly=bitmap.getHeight()- cropView.getWidth()-viewleft.getWidth();//判断剪裁范围是否超出照片范围if ((lx+cropView.getHeight())>bitmap.getWidth()||(ly+cropView.getWidth())>bitmap.getHeight()){cropBitmap=bitmap;}else{cropBitmap = Bitmap.createBitmap(bitmap,(int) lx,(int) ly,(int) cropView.getHeight(),(int) cropView.getWidth());}}else{int lx2;if (Utils.checkDeviceHasNavigationBar2(ScanCardActivity.this)){lx2=viewtop.getHeight()-statusBarHeight+NavUtils.getNavigationBarHeight(ScanCardActivity.this);}else{lx2=viewtop.getHeight()-statusBarHeight;}//判断剪裁范围是否超出照片范围if ((viewleft.getWidth()+w)>bitmap.getWidth()||(lx2+h)>bitmap.getHeight()){cropBitmap=bitmap;}else{cropBitmap = Bitmap.createBitmap(bitmap,(int) viewleft.getWidth(),(int)lx2,(int)  w,(int)h);}}final File cropFile = getCropFile();BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(cropFile));cropBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);bos.flush();bos.close();Handler mainHandler = new Handler(Looper.getMainLooper());mainHandler.post(new Runnable() {@Overridepublic void run() {//已在主线程中,可以更新UIpostImageCard(cropFile);}});runOnUiThread(new Runnable() {@Overridepublic void run() {
//                                        resultView.setVisibility(View.VISIBLE);}});return;} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}runOnUiThread(new Runnable() {@Overridepublic void run() {
//                                optionView.setVisibility(View.VISIBLE);cameraSurface.setEnabled(true);}});}}).start();Loger.debug("Bitmap  containerView.getWidth()  :  " + containerView.getWidth());Loger.debug("Bitmap  containerView.getHeight()  :  " + containerView.getHeight());TranslateAnimation translateAni = new TranslateAnimation(//X轴初始位置Animation.ABSOLUTE, 0.0f,//X轴移动的结束位置Animation.ABSOLUTE, 0.0f,//y轴开始位置Animation.ABSOLUTE, 0.0f,//y轴移动后的结束位置Animation.ABSOLUTE, containerView.getHeight());//                Animation.RELATIVE_TO_PARENT,  containerView.getX(), Animation.RELATIVE_TO_PARENT,
//                        containerView.getX()+containerView.getWidth(), Animation.RELATIVE_TO_PARENT, containerView.getY(),
//                        Animation.RELATIVE_TO_PARENT, containerView.getY()//                );//设置动画执行的时间,单位是毫秒translateAni.setDuration(3000);// 设置动画重复次数// -1或者Animation.INFINITE表示无限重复,正数表示重复次数,0表示不重复只播放一次translateAni.setRepeatCount(10);// 设置动画模式(Animation.REVERSE设置循环反转播放动画,Animation.RESTART每次都从头开始)translateAni.setRepeatMode(Animation.REVERSE);translateAni.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {ivScanLine.setVisibility(View.GONE);}@Overridepublic void onAnimationRepeat(Animation animation) {}});// 启动动画ivScanLine.startAnimation(translateAni);}});

主要修改就是剪裁图片的时候,要区别拍照后是横向图片还是竖向照片,然后为了防止有没有测试到的情况直接检测裁剪的范围是否超过了原图,加入了长宽与原图的判断,在最后运行扫描条来回移动的动画。

基本的修改就这些了,最后在handler中放入获取剪裁图片后的下一步处理。

本文暂时用于自己日后参考,可能会有些代码不全的地方

 

 

 

这篇关于Android扫描名片的动画以及剪裁扫描框的图片的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145105

相关文章

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

利用Python脚本实现批量将图片转换为WebP格式

《利用Python脚本实现批量将图片转换为WebP格式》Python语言的简洁语法和库支持使其成为图像处理的理想选择,本文将介绍如何利用Python实现批量将图片转换为WebP格式的脚本,WebP作为... 目录简介1. python在图像处理中的应用2. WebP格式的原理和优势2.1 WebP格式与传统

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级

基于 HTML5 Canvas 实现图片旋转与下载功能(完整代码展示)

《基于HTML5Canvas实现图片旋转与下载功能(完整代码展示)》本文将深入剖析一段基于HTML5Canvas的代码,该代码实现了图片的旋转(90度和180度)以及旋转后图片的下载... 目录一、引言二、html 结构分析三、css 样式分析四、JavaScript 功能实现一、引言在 Web 开发中,

Python如何去除图片干扰代码示例

《Python如何去除图片干扰代码示例》图片降噪是一个广泛应用于图像处理的技术,可以提高图像质量和相关应用的效果,:本文主要介绍Python如何去除图片干扰的相关资料,文中通过代码介绍的非常详细,... 目录一、噪声去除1. 高斯噪声(像素值正态分布扰动)2. 椒盐噪声(随机黑白像素点)3. 复杂噪声(如伪

Python中图片与PDF识别文本(OCR)的全面指南

《Python中图片与PDF识别文本(OCR)的全面指南》在数据爆炸时代,80%的企业数据以非结构化形式存在,其中PDF和图像是最主要的载体,本文将深入探索Python中OCR技术如何将这些数字纸张转... 目录一、OCR技术核心原理二、python图像识别四大工具库1. Pytesseract - 经典O

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取