起源
针对相机开发涉及专业知识多,且Camera2使用复杂等痛点,在2019年的Google I/O大会上,Google推出了一个新的Jetpack组件--CameraX,这个支持包的作用为: help you make camera app development easier
优势
- 适用大部分android设备,且向后兼容至Android5.0(API level 21)
- 基于Use Case设计,api使用简单,且代码量更少
- 与Lifecycle组件结合,自动管理相机的生命周期
- 与主流手机厂商合作,通过CameraX可以使用手机厂商系统相机app独有的人像,美颜,hdr等效果
基本使用
CameraX基于Use Case进行设计,使调用者专注于需要完成的任务,而无需花时间处理不同设备的细微差别, 目前包括三种基本用例:
- Preview
- Image Analysis
- Capture
不管是预览还是图像分析,图片拍摄,CameraX用例的使用都遵循一个统一的基本流程:
- 通过建造者模式构建Config类;
- 通过Config类创建Case;
- 绑定生命周期
CameraX目前处于alpha版本,在使用时需要先添加依赖:
代码语言:javascript复制def camera_x_version = "1.0.0-alpha06"
implementation "androidx.camera:camera-core:${camera_x_version}"
implementation "androidx.camera:camera-camera2:${camera_x_version}"
预览
代码语言:javascript复制// 1. create config
val previewConfig = PreviewConfig.Builder()
.setLensFacing(CameraX.LensFacing.FRONT)
.build()
// 2. create case
val preview = Preview(previewConfig)
// 3. register first frame
preview.setOnPreviewOutputUpdateListener {
mTextureView.surfaceTexture = it.surfaceTexture
}
// 4. binding
CameraX.bindToLifecycle(this, preview)
拍照
代码语言:javascript复制// 1. create config
val imageCaptureBuildConfig = ImageCaptureConfig.Builder()
.setLensFacing(CameraX.LensFacing.FRONT)
.setTargetRotation(windowManager.defaultDisplay.rotation)
.setCaptureMode(ImageCapture.CaptureMode.MAX_QUALITY)
.build()
// 2. create case
val capture = ImageCapture(imageCaptureBuildConfig);
// 3. binding
CameraX.bindToLifecycle(this, capture)
// 4. take photo
capture.takePicture(...)
图像分析
通过对图像分析用例注册analyze方法(该方法每帧执行一次),我们可以获取到每一帧的图像数据。拿到图像数据后,就可以根据自己的业务进行相关操作了。 图像分析可以分为两种模式:阻塞模式和非阻塞模式。
阻塞模式通过 ImageAnalysis.ImageReaderMode.ACQUIRE_NEXT_IMAGE 设置,在此模式下, 分析器会按顺序从相机接收帧;
非阻塞模式通过 ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE 设置。在此模式下,分析器会从相机接收调用 analyze 方法时的最后一个可用帧。该模式是可能丢帧的。
代码语言:javascript复制// 1. create config
val imageAnalysisConfig = ImageAnalysisConfig.Builder()
.setLensFacing(CameraX.LensFacing.FRONT)
.setTargetResolution(Size(1280, 720))
.setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
.build()
// 2. create case
val imageAnalysis = ImageAnalysis(imageAnalysisConfig)
// 3. register analyzer
imageAnalysis.setAnalyzer(mExecutor, { image: ImageProxy, rotationDegrees: Int ->
// image format -> YUV_420_888
})
CameraX.bindToLifecycle(this, imageAnalysis)
供应商扩展
手机厂商的系统相机app有很多优秀的相机效果,比如虚化bokeh,hdr,美颜等,第三方相机app可以通过CameraX Extensions使用到这些效果,如果厂商支持,否则采用CameraX的默认实现
代码语言:javascript复制// Create a Builder same as in normal workflow.
val builder = ImageCaptureConfig.Builder()
// Create a Extender object which can be used to apply extension
// configurations.
val bokehImageCapture = BokehImageCaptureExtender.create(builder)
// Query if extension is available (optional).
if (bokehImageCapture.isExtensionAvailable()) {
// Enable the extension if available.
bokehImageCapture.enableExtension()
}
// Finish constructing configuration with the same flow as when not using
// extensions.
val config = builder.build()
val useCase = ImageCapture(config)
CameraX.bindToLifecycle(this as LifecycleOwner, useCase)
CameraX OpenGL
在预览用例中,通过注册setOnPreviewOutputUpdateListener,可以拿到一个相机图像流的SurfaceTexture, 通过SurfaceTexture的attachToGLContext
方法将一个OES纹理关联到GL环境中:
Attach the SurfaceTexture to the OpenGL ES context that is current on the calling thread. A This new texture is bound to the GL_TEXTURE_EXTERNAL_OES texture target.
然后将OES纹理绘制到OpenGL对应的Surface上
DEMO
https://github.com/sifutang/camerax_demo.git
demo效果: