CameraX + Zxing 竖屏实现 一维码、二维码扫描

news/2024/11/30 12:25:50/

分为两步

一.获取图像数据

二.利用zxing分析图像数据

下面先看下识别效果

识别效果

这个demo是直接基于官方demo修改而成的,有兴趣的小伙伴可以直接上官网下载去

一.获取图像数据

首先我们需要知道Camerax功能分成三个用例了,分别是:预览,分析,拍照,由于我们做的是二维码分析,所以只需要用到预览和分析两个用例

1.导入CameraX所需用到的包

    //CameraX依赖模块def camerax_version = '1.0.0-beta04'implementation "androidx.camera:camera-core:$camerax_version"// CameraX Camera2 拓展implementation "androidx.camera:camera-camera2:$camerax_version"// CameraX Lifecycle libraryimplementation "androidx.camera:camera-lifecycle:$camerax_version"// CameraX Viewimplementation 'androidx.camera:camera-view:1.0.0-alpha11'

2.布局,这边布局很简单就一个PreviewView

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/camera_container"android:background="@android:color/black"android:layout_width="match_parent"android:layout_height="match_parent"><androidx.camera.view.PreviewViewandroid:id="@+id/view_finder"android:layout_width="match_parent"android:layout_height="match_parent" /></androidx.constraintlayout.widget.ConstraintLayout>

3.初始化相机,和Camera2比起来,确实少了很多代码,而且不需要自己管理相机的生命周期,属实有点舒服,这里权限申请什么的我就不细说了

 private fun bindCameraUseCases() {// 获取用于设置全屏分辨率相机的屏幕值val metrics = DisplayMetrics().also { viewFinder.display.getRealMetrics(it) }//获取使用的屏幕比例分辨率属性val screenAspectRatio = aspectRatio(metrics.widthPixels / 2, metrics.heightPixels / 2)val width = viewFinder.measuredWidthval height = if (screenAspectRatio == AspectRatio.RATIO_16_9) {(width * RATIO_16_9_VALUE).toInt()} else {(width * RATIO_4_3_VALUE).toInt()}val size = Size(width, height)//获取旋转角度val rotation = viewFinder.display.rotation//和Fragment的生命周期绑定val cameraSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()//设置所选相机val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())cameraProviderFuture.addListener(Runnable {val cameraProvider = cameraProviderFuture.get()// 预览用例preview = Preview.Builder().setTargetResolution(size).setTargetRotation(rotation).build()//拍照用例imageCapture = ImageCapture.Builder().setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY).setTargetResolution(size).setTargetRotation(rotation).build()// 图像分析用例imageAnalyzer = ImageAnalysis.Builder().setTargetResolution(size).setTargetRotation(rotation).build().apply {//核心类BarCodeAnalyzersetAnalyzer(cameraExecutor, BarCodeAnalyzer(object : OnBack {override fun back(code: String) {activity?.apply {runOnUiThread {Toast.makeText(this, code, Toast.LENGTH_SHORT).show()}}}}))}// 必须在重新绑定用例之前取消之前绑定cameraProvider.unbindAll()try {//获取相机实例camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture, imageAnalyzer)//设置预览的viewpreview?.setSurfaceProvider(viewFinder.createSurfaceProvider())} catch (exc: Exception) {Log.e(TAG, "Use case binding failed", exc)}}, ContextCompat.getMainExecutor(requireContext()))}

这些代码是初始化相机的代码,因为是官方demo,所以比较详细,一共包含了preview,imageCupture,imageAnalyzer三个用例,分别是预览用例,拍照用例,分析用例,我们二维码分析只需要使用preview,imageAnalyzer用例,此时我们初始化的环节已经做好了,重点部分来了,我们来看看我们的测试用例类BaeCodeAnalyzer.class,代码如下

    private class BarCodeAnalyzer(val onBack: OnBack) : ImageAnalysis.Analyzer {private val reader: MultiFormatReader = initReader()/*** 将buffer写入数组*/private fun ByteBuffer.toByteArray(): ByteArray {rewind()val data = ByteArray(remaining())get(data)return data}override fun analyze(image: ImageProxy) {//图片分析//如果不是yuv_420_888格式直接不处理if (ImageFormat.YUV_420_888 != image.format) {Log.e("BarcodeAnalyzer", "expect YUV_420_888, now = ${image.format}")image.close()return}//将buffer数据写入数组val data = image.planes[0].buffer.toByteArray()//获取图片宽高val height = image.heightval width = image.width//将图片旋转,这是竖屏扫描的关键一步,因为默认输出图像是横的,我们需要将其旋转90度val rotationData = ByteArray(data.size)Log.i(TAG, "rotationDataSize :${data.size}  ## height:$height ## width:$width")var j: Intvar k: Intfor (y in 0 until height) {for (x in 0 until width) {j = x * height + height - y - 1k = x + y * widthrotationData[j] = data[k]}}//zxing核心解码块,因为图片旋转了90度,所以宽高互换,最后一个参数是左右翻转val source = PlanarYUVLuminanceSource(rotationData, height, width, 0, 0, height, width, false)val bitmap = BinaryBitmap(HybridBinarizer(source))try {val result = reader.decode(bitmap)Log.i("Resultkkk", ":扫码成功: ${result.text}")onBack.back(result.text)} catch (e: Exception) {image.close()} finally {image.close()}}private fun initReader(): MultiFormatReader {val formatReader = MultiFormatReader()val hints = Hashtable<DecodeHintType, Any>()val decodeFormats = Vector<BarcodeFormat>()//添加一维码解码格式decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS)//这个不知道干啥的,可以不加decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS)//添加二维码解码格式decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS)hints[DecodeHintType.POSSIBLE_FORMATS] = decodeFormats//设置解码的字符类型hints[DecodeHintType.CHARACTER_SET] = "UTF-8"//这边是焦点回调,就是找到那个条码的所在位置,这里我不处理
//        hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK] = mPointCallBackformatReader.setHints(hints)return formatReader}}

我们目前只需要关注analyze这个方法,这是个抽象方法,这个方法的就类似于传统相机的Camera.PreviewCallback的回调,用于分析图片,这是个默认是个阻塞式方法,里面包含的ImageProxy就是我们需要使用的了,此时我们已经完成了图像数据获取了

二.分析利用zxing分析图像数据

1.初始化Reader解码器

这里我们设置一下我们需要解析的条码类型

        private val reader: MultiFormatReader = initReader()private fun initReader(): MultiFormatReader {val formatReader = MultiFormatReader()val hints = Hashtable<DecodeHintType, Any>()val decodeFormats = Vector<BarcodeFormat>()//添加一维码解码格式decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS)//这个不知道干啥的,可以不加decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS)//添加二维码解码格式decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS)hints[DecodeHintType.POSSIBLE_FORMATS] = decodeFormats//设置解码的字符类型hints[DecodeHintType.CHARACTER_SET] = "UTF-8"//这边是焦点回调,就是找到那个条码的所在位置,这里我不处理
//        hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK] = mPointCallBackformatReader.setHints(hints)return formatReader}

2.开始解析

在Analyze方法中,首先我们将ImageProxy包含的数据获取下来,此处默认返回类型是YUV_420_888,如果不是这种格式直接返回,如果是这种格式,那么我们获取它的数据写入到数组当中,并且获取宽高,此时注意我们写入的数据是横屏的图片数据

            //如果不是yuv_420_888格式直接不处理if (ImageFormat.YUV_420_888 != image.format) {Log.e("BarcodeAnalyzer", "expect YUV_420_888, now = ${image.format}")image.close()return}//将buffer数据写入数组val data = image.planes[0].buffer.toByteArray()//获取图片宽高val height = image.heightval width = image.width

将图片旋转90度

            //将图片旋转,这是竖屏扫描的关键一步,因为默认输出图像是横的,我们需要将其旋转90度val rotationData = ByteArray(data.size)Log.i(TAG, "rotationDataSize :${data.size}  ## height:$height ## width:$width")var j: Intvar k: Intfor (y in 0 until height) {for (x in 0 until width) {j = x * height + height - y - 1k = x + y * widthrotationData[j] = data[k]}}

此时我们获取到了rotationData,这就是旋转之后的数据了,我们现在开始使用我们的reader开始解析

            //zxing核心解码块,因为图片旋转了90度,所以宽高互换,最后一个参数是左右翻转val source = PlanarYUVLuminanceSource(rotationData, height, width, 0, 0, height, width, false)val bitmap = BinaryBitmap(HybridBinarizer(source))try {val result = reader.decode(bitmap)Log.i("Resultkkk", ":扫码成功: ${result.text}")onBack.back(result.text)} catch (e: Exception) {image.close()} finally {image.close()}

当没有异常抛出的时候,这时候我们就是解析成功了,此时大功告成。

项目地址:https://gitee.com/gongzhaoyang/demo.git


http://www.ppmy.cn/news/420723.html

相关文章

Android studio 手机扫描二维码功能

安卓手机版本在6.0以后需要动态获取相机权限1.获取相机权限 <!-- 获取手机相机的权限 --><uses-permission android:name"android.permission.CAMERA" /><uses-permission android:name"android.permission.FLASHLIGHT" />2.添加依赖 …

Android使用ZXing扫描二维码,并返回二维码结果

1.首先到https://github.com/zxing/zxing上下载zxing最新版本是3.3.1 2.解压zxing&#xff0c;我们主要使用下图所示的两个目录 3.把上图中的两个目录中的代码拷贝到你的Android项目中&#xff0c;下面是我的项目目录 4.把zxing中的layout目录中布局文件拷贝到你的项目对应目录…

zxing 二维码扫描 配置和使用

二维码扫描使用最多的主要有两个库&#xff1a;zbarSDK 和zxing 关于zbar的使用比较简单&#xff0c;在这里不多说了&#xff0c;对于zxing的使用就比较麻烦&#xff0c;虽然网上有很多关于zxing的使用方法&#xff0c;不过查了很多中文和英文的贴子。发现说的都不够详细&…

使用Zxing实现Android二维码扫描

现在市场上的很多Android应用具有二维码扫描的功能&#xff0c;本文将介绍如何将Zxing集成到自己的项目中实现二维码扫描的功能项目中使用的zxing版本是3.2.0应该是最新的&#xff0c;这里附上github上的zxing项目的链接&#xff08;百度太让人无语了&#xff0c;搜zxing第一页…

Android 使用Zxing实现二维码的生成,扫描

在项目中要使用到二维码的相关内容,百度(原谅我还在用)之后得知一半都是使用Google的开源库 Zxing,但是网上多半的使用教程都是比较早的,这里给出我总结的一些基础代码和使用规则: 首先要一定要先去官网看看: github-Zxing官方库的地址 github-zxing-android-embedde…

使用ZXing扫码实现扫手机本地图片的二维码内容

ZXing这个第三方是我用的第三方&#xff0c;用来扫描二维码的&#xff0c;之前没有看到ZXing还提供了扫描本地图片二维码的功能&#xff0c;现在整理如下。 跳转到选取本地图片的页面 Intent intent new Intent(Intent.ACTION_GET_CONTENT);intent.setType("iamge/*&quo…

xamarin.forms 使用ZXing扫描二维码

1. Android工程包含ZXing.Net.Mobile.Forms 2. 在C# 工程中, 包含ZXing.Net.Mobile 3. 在Android工程的MainActivity.cs中, 添加下面代码: global::ZXing.Net.Mobile.Forms.Android.Platform.Init(); ZXing.Mobile.MobileBarcodeScanner.Initialize(this.Application); usin…

TC8:SOMEIPSRV_ONWIRE_01-12

SOMEIPSRV_ONWIRE_01: IP addresses and port number of the Reponse message 目的 检查SOME/IP响应消息的ip地址和port端口与请求消息匹配 测试步骤 DUT CONFIGURE:启动具有下列信息的服务 – Service ID:SERVICE-ID-1 – Instance数量:1Tester:客户端-1发送SOME/IP Noti…