赞
踩
零蚀
[camerax 官方文档(翻墙)](这是一个高能网站,很多相关的google教程都在这)
配置 ->动态权限 ->预览->文件->YUV_420_888转bitmap
alpha06 的camerax 版本
// Use the most recent version of CameraX, currently that is alpha06.
ext {
amerax_version = '1.0.0-alpha06'
}
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
还需要jdk1.8的支持
// android 下
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
camera显示控件TextureView
<TextureView
android:id="@+id/view_finder"
android:layout_width="640px"
android:layout_height="640px"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
权限(动态权限)
<uses-permission android:name="android.permission.CAMERA" />
// 获取权限 if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) !=PERMISSION_GRANTED){ ActivityCompat.requestPermissions(this, arrayOf( Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA ),10001) }else{ LogUtil.d("已经申请了权限") normalInit() } // 权限返回值 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if(requestCode==10001){ permissions.forEachIndexed { index, it -> if(grantResults[index]==0) { LogUtil.d("权限: $it 申请成功") }else{ LogUtil.d("权限: $it 申请失败") } } // 初始化摄像头等操作 normalInit() } }
添加监听
object CameraBaseUtil{
.....
fun initCameraListener(view:TextureView){
view.addOnLayoutChangeListener { v,
left, top, right, bottom,
oldLeft, oldTop, oldRight, oldBottom ->
LogUtil.d("camera的监听发生改变")
}
}
....
构建camera,启动,变化,结束的demo
object CameraWorkUtil { private var preview:Preview?=null enum class CameraStatus { START, UPDATE, FINISH } fun initCameraListener(view: TextureView) { view.addOnLayoutChangeListener { v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom -> //action(this,view,CameraStatus.UPDATE) LogUtil.d("camera的监听发生改变") } } fun action(owner: LifecycleOwner, view: TextureView, status: CameraStatus) { when (status) { CameraStatus.START -> startCamera(owner, view) CameraStatus.UPDATE -> upDataCamera() CameraStatus.FINISH -> finishCamera() } } private fun finishCamera() { if (preview!=null) { CameraX.unbind(preview) } } private fun upDataCamera() { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } private fun startCamera(owner: LifecycleOwner, viewFinder: TextureView) { // 创建配置对象,供给TextureView使用 val previewConfig = PreviewConfig.Builder().apply { setTargetResolution(Size(640, 480)) }.build() // 构建使用场景 preview = Preview(previewConfig) // 每当发生变化都会使得,重新计算&布局 preview.setOnPreviewOutputUpdateListener { val parent = viewFinder.parent as ViewGroup parent.removeView(viewFinder) parent.addView(viewFinder, 0) viewFinder.surfaceTexture = it.surfaceTexture //upDataCamera() } CameraX.bindToLifecycle(owner,preview) } }
获取图像的文件操作
private fun startCamera(owner: LifecycleOwner, viewFinder: TextureView) { val previewConfig = PreviewConfig.Builder().apply { setTargetResolution(Size(640,640)) }.build() val preview=Preview(previewConfig) // 每当发生变化都会使得,重新计算&布局 preview.setOnPreviewOutputUpdateListener { val parent = viewFinder.parent as ViewGroup parent.removeView(viewFinder) parent.addView(viewFinder, 0) viewFinder.surfaceTexture = it.surfaceTexture //upDataCamera() } // 捕获图像(它自己氛围低质和高质两种图像,差异在于获取的时间) // 这里不在设置分辨率,而是相位定量 val imageCaptureConfig = ImageCaptureConfig.Builder() .apply { setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY) }.build() // 将图像捕捉的场景依附于点击监听上。 imageCapture = ImageCapture(imageCaptureConfig) CameraX.bindToLifecycle(owner, preview , imageCapture) } fun getPictureConfig(file:File,listener:OnCameraCaptureInter){ imageCapture?.takePicture(file, Executors.newCachedThreadPool(), object :ImageCapture.OnImageSavedListener{ override fun onImageSaved(file: File) { listener.success(file) } override fun onError(imageCaptureError: ImageCapture.ImageCaptureError, message: String, cause: Throwable?) { listener.error(message) } }) }
ivCaptureButton.setOnClickListener { val file=File(Environment.getExternalStorageDirectory().absolutePath+ File.separator+ Environment.DIRECTORY_PICTURES, "${System.currentTimeMillis()}.jpg") LogUtil.e(file.absolutePath) CameraBaseUtil.getPictureConfig(file,object:OnCameraCaptureInter{ override fun success(file: File) { toast("the file's path is ${file.path}") } override fun error(message: String) { toast(message) } }) }
获取图像像素矩阵,并转为bitmap(划重点,官网没有)
首先我们要知道camerax默认的iamgeFormat是YUV_420_888,而一般我们转为图片的格式只有NV21和YUY2所以采用YuvImage来转图片的byteArray是行不通的。(我们从camera直接拿到的byteArray是不能进行直接的Bitmap的,可以了解一下YUV),所以为了转换计算方便需要用到NDK来处理这些byte转换问题
具体转化方法可以看**[
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。