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 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Python利用PIL进行图片压缩

《Python利用PIL进行图片压缩》有时在发送一些文件如PPT、Word时,由于文件中的图片太大,导致文件也太大,无法发送,所以本文为大家介绍了Python中图片压缩的方法,需要的可以参考下... 有时在发送一些文件如PPT、Word时,由于文件中的图片太大,导致文件也太大,无法发送,所有可以对文件中的图

java获取图片的大小、宽度、高度方式

《java获取图片的大小、宽度、高度方式》文章介绍了如何将File对象转换为MultipartFile对象的过程,并分享了个人经验,希望能为读者提供参考... 目China编程录Java获取图片的大小、宽度、高度File对象(该对象里面是图片)MultipartFile对象(该对象里面是图片)总结java获取图片

Java实战之自助进行多张图片合成拼接

《Java实战之自助进行多张图片合成拼接》在当今数字化时代,图像处理技术在各个领域都发挥着至关重要的作用,本文为大家详细介绍了如何使用Java实现多张图片合成拼接,需要的可以了解下... 目录前言一、图片合成需求描述二、图片合成设计与实现1、编程语言2、基础数据准备3、图片合成流程4、图片合成实现三、总结前

使用Python实现图片和base64转换工具

《使用Python实现图片和base64转换工具》这篇文章主要为大家详细介绍了如何使用Python中的base64模块编写一个工具,可以实现图片和Base64编码之间的转换,感兴趣的小伙伴可以了解下... 简介使用python的base64模块来实现图片和Base64编码之间的转换。可以将图片转换为Bas

css实现图片旋转功能

《css实现图片旋转功能》:本文主要介绍了四种CSS变换效果:图片旋转90度、水平翻转、垂直翻转,并附带了相应的代码示例,详细内容请阅读本文,希望能对你有所帮助... 一 css实现图片旋转90度.icon{ -moz-transform:rotate(-90deg); -webkit-transfo

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

C#实现添加/替换/提取或删除Excel中的图片

《C#实现添加/替换/提取或删除Excel中的图片》在Excel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更加美观,下面我们来看看如何在C#中实现添加/替换/提取或删除E... 在Excandroidel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更

SQL注入漏洞扫描之sqlmap详解

《SQL注入漏洞扫描之sqlmap详解》SQLMap是一款自动执行SQL注入的审计工具,支持多种SQL注入技术,包括布尔型盲注、时间型盲注、报错型注入、联合查询注入和堆叠查询注入... 目录what支持类型how---less-1为例1.检测网站是否存在sql注入漏洞的注入点2.列举可用数据库3.列举数据库