CameraX 是一个 Jetpack 支持库,旨在帮助您简化相机应用的开发工作。它提供一致且易用的 API 接口,适用于大多数 Android 设备,并可向后兼容至 Android 5.0 (API 级别 21)。我们将在本文中介绍 CameraX 1.1 的多项功能,比如视频功能。
CameraX 概览
CameraX 是一个为了简化编写相机应用而设计的支持库,它所提供的高级 API 可以让开发者专注于和用户交互而非相机的内部实现。我们一直在探索并修复其背后复杂的兼容性问题,让每个新版本都得以在更多的设备上稳定运行。
何时使用 CameraX 或 Camera2,这取决于您期望更快的开发速度或是想要更高的自定义程度。
CameraX 可以很方便地实现普通照片视频的拍摄功能,而 Camera2 则可以对拍摄流程进行特殊控制,例如实现多重曝光或全手动捕获;
CameraX 旨在消除不同设备间的差异并在不同设备上进行了测试,而 Camera2 则需要应用来管理不同设备间的差异并测试其行为;
CameraX 提升了代码开发速度,让您更专注于用户界面和体验流程,而 Camera2 则用于更深入地开发以创造基于相机的定制功能;
CameraX 发布新版本频繁,而 Camera2 则随着 Android 的版本而更新;
CameraX 可以在您不熟悉相机的情况下也能够进行开发,而 Camera2 则需要您对相机的专业知识有更深层次的了解。
CameraX 基于主要的使用场景来构建,比如实时预览相机、检索缓冲区以进行分析和拍摄照片,在 CameraX 1.1 版本中还加入了视频拍摄功能。我们来看一个简单的 CameraX 示例:
fun bindPreview(cameraProvider : ProcessCameraProvider) {
// 使用 CameraX 创建 Preview 用例
var preview : Preview = Preview.Builder().build()
// 创建 cameraSelector,它会在设备上搜索所需的相机
var cameraSelector : CameraSelector = CameraSelector.Builder()
// 在本例中,我们选择搜索后置相机
.requireLensFacing(CameraSelector.LENS_FACING_BACK).build()
// 从 CameraX 的 CameraView 包中获取 previewView 的句柄
// 利用此方法可以轻松的将相机内容添加到视图上
preview.setSurfaceProvider(previewView.getSurfaceProvider())
// 将 preview 与其生命周期绑定
var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner,
cameraSelector, preview)
}
△ CameraX 代码示例
CameraX 是生命周期感知型组件,这意味着它将自动处理应用的生命周期事件来实现开始、停止、暂停和恢复。现在,应用启动时屏幕上便会显示实时预览。
我们已于 2021 年 5 月发布了 1.0 稳定版本,目前正在开发 1.1 Alpha 版本并且很快将会进入 Beta 阶段。并且我们一如既往地不断为新增设备推出兼容性修复程序,例如 1.0.1 和 1.0.2。
在 CameraX 1.1 版本中我们新增了开发者呼声很高的功能,具体而言,在本文中我们将重点介绍:
视频拍摄
YUV 到 RGB 的转换
Beta 版 Extensions API
一些需要了解的其它功能
视频拍摄在 CameraX 1.1 版本中我们加入了视频拍摄功能,视频拍摄 API (尚处于 Alpha 阶段,细节可能会发生变化,但整体结构基本会保持不变) 提供了录制到文件等基本功能、可自动适配每台设备的 Quality Setting API,以及 Lifecycle Management API。接下来我们先来了解如何设定视频拍摄功能,代码示例如下:
// 创建 Recorder
val recorder = Recorder.Builder()
// 我们可以在此处使用 setQualitySelector 设置视频质量
.setQualitySelector(...)
.build()
// 使用新创建的 Recorder 创建 VideoCapture
val videoCapture = VideoCapture.withOutput(recorder)
// 将其与生命周期绑定
cameraProvider.bindToLifecycle(
this, CameraSelector.DEFAULT_BACK_CAMERA, preview, videoCapture)
// 设定 VideoRecordEvent 监听器
val videoRecordEventListener = Consumer{
when (it) {
is VideoRecordEvent.Start -> {}
is VideoRecordEvent.Finalize -> {}
is VideoRecordEvent.Status -> {
// status 事件将会在录制时持续更新
val stats: RecordingStats = it.recordingStats
// RecordingStats 中包含录制文件的尺寸和时长
}
is VideoRecordEvent.Pause -> {}
is VideoRecordEvent.Resume -> {}
// 指定输出
val mediaStoreOutput = MediaStoreOutputOptions.Builder(this.contentResolver,
MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
.setContentValues(contentValues)
.build()
// 准备录制
val activeRecording = videoCapture.output.prepareRecording(this, mediaStoreOutput)
// 关联事件监听器
.withEventListener(ContextCompat.getMainExecutor(this), videoRecordEventListener)
// 启用音频 (前提是此应用已获得音频权限)
.withAudioEnabled()
// 开始录制
.start()
△ 视频拍摄示例
videoCapture 会在应用启动时就绪,应用可以使用 videoRecordEventListener 响应开始、结束、暂停和恢复等拍摄事件,其中 Status 事件会提供包括文件大小和持续时间的 RecordingStats。视频拍摄可以输出到 File、FileDescriptor 或 MediaStore,在本例中我们选择 MediaStore。如果选择启用音频,则需要此应用已经获得音频权限。调用 start() 开始录制为我们提供了 activeRecording 句柄,它可以用来暂停、恢复或停止录制。您可以在 1.1 版本中试用这些 API。
YUV 至 RGB 的转换
另一个呼声很高的功能是 YUV 到 RGB 的转换,我们来了解一下此功能。
相机通常以 YUV420 格式生成数据,其中包括明亮度 (Luminance, Y)、色度 (Chroma, U, V) 和一些填充字节以将各行与有效的内存步幅对齐。但是这种格式的图像处理起来可能很麻烦,而现在 CameraX 可以将 ImageAnalysis 的输出转换为大家更熟悉的 RGBA 以方便处理。接下来我们看一个示例:
val imageAnalysis = ImageAnalysis.Builder()
.setTargetResolution(Size(1280, 720))
.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
△ 从 ImageAnalysis 获取 RGB 输出
在示例代码中,我们创建了 ImageAnalysis 实例,为图像缓冲区指定了所需的分辨率和背压策略,并调用新的 setOutputImageFormat 方法以请求 RGBA 8888 格式的输出。现在,ImageAnalysis 输出的帧为 RGBA 8888 数据而不再是 YUV 格式。
CameraX 中 YUV 到 RGB 的转换基于 libyuv。此外,在 CameraX 1.1 版本中数据本身可以转换到目标分辨率。在中端设备上对图像大小为 640x480 至 1080p 的数据进行转换大约需要 5~10 毫秒,具体性能因设备而异。此外 APK 会略微增加 50KB 左右。
修复单像素漂移
CameraX Extensions API
相机特效在 CameraX 1.1 中的 CameraX Extensions API 可以更为充分地发挥设备强大的功能。
CameraX Extensions 包括一些最常见的内置相机特效:
BOKEH (焦外虚化): 在人像模式下拍摄照片时,让前景人物更清晰。
HDR (高动态范围): 拍照时使用不同的自动曝光 (AE) 配置,以获得最佳效果。
NIGHT (夜间): 在低照度环境下 (通常是在夜间) 捕获最佳静态图像。
FACE RETOUCH (脸部照片修复): 拍摄静态图像时,修饰脸部肤色、轮廓等。
AUTO (自动): 根据周围的景色自动调整最终图像。
我们来看看如何使用 CameraX Extensions API:
△ 以 BOKEH 效果捕捉并预览图像// 获取后置相机列表
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
// 检查所有的后置相机中是否有支持焦外虚化
if (extensionsManager.isExtensionAvailable(
cameraProvider,
cameraSelector,
ExtensionMode.BOKEH
)) {
// 创建扩展 cameraSelector,我们提供了相机并指定焦外虚化模式
// 它将开始在后台搜索支持焦外虚化的后置相机
val bokehCameraSelector = extensionsManager.getExtensionCameraSelector(
cameraProvider,
cameraSelector,
ExtensionMode.BOKEH
)
// 创建 imageCapture 和 preview
val imageCapture = ImageCapture.Builder().builder()
val preview = Preview.Builder().build()
// 使用 bokehCameraSelector 将它们绑定到生命周期
cameraProvider.bindToLifecycle(lifecycleOwner,
bokehCameraSelector,
imageCapture,
preview
)
}
在上面的例子中,imageCapture 输出的图像将会具有焦外虚化效果,如果设备支持的话,preview 也将预览焦外虚化效果。
曝光补偿
CameraX 1.1 中还添加了曝光补偿 API,此功能可以帮助用户更好地捕捉过度曝光或者曝光不足的区域。
如图所示我们所处的场景窗外很明亮而室内很昏暗,此时则可以调整曝光补偿来更好地捕捉明亮的室外或昏暗的室内场景。我们来看一个例子:
// 创建变量来跟踪 exposureIndex 值
var exposureIndex = 0
// 使用 cameraSelector 将 imageCapture 和 preview 绑定到生命周期
val camera = cameraProvider.bindToLifecycle(
lifecycleOwner,
getCameraSelector(),
preview,
imageCapture
)
// 为视图中的按钮添加点击事件
evButton.setOnclickListener {
// 检查有效的范围以防止可能的异常
val range = camera.cameraInfo.exposureState.exposureCompensationRange
if (range.contains(exposureIndex + 1)) {
// 调用 camera.cameraControl 的 setExposureCompenstation() 方法来设置曝光补偿
camera.cameraControl.setExposureCompenstation(++exposureIndex)
// 使用 exposureCompensationStep 来实现从 index 到 EV 到转换
val ev = camera.cameraInfo.exposureState.exposureCompensationStep.toFloat() * exposureIndex
Log.i("CameraXLog", "EV: $ev")
}
}
△ 通过按钮调整曝光
其中 exposureIndex 是一个与设备无关的数字,它将以硬件允许的最小步长递增或递减曝光值,因此可以在不同的设备上以类似的方式运作。如果您想向用户展示 EV 值,可以获取 exposureCompensationStep 来实现转换。
平滑缩放
在 CameraX 1.1 中,我们还增加了平滑缩放功能。有一些设备有包括广角和长焦在内的多个镜头,CameraX 可以检测这些设备是否支持 SMOOTH_ZOOM 框架,在受支持的设备上使用 CameraX 的缩放控件时,会自动使用所有的相机来实现更大的缩放范围。如果您已经在使用这个缩放控件,那当您使用 1.1 版本进行编译时,您的应用应该就可以访问这些设备上的所有相机。
CameraX 1.1 的更多功能
接下来介绍我们在 1.1 中添加的更多功能。
CameraState API 现在可以提供诸如另一个应用正在使用相机或者正处于勿扰模式等更多有关相机状态的信息,使得应用能够围绕不同的相机时间来设计更好的界面和用户体验流程。Image Analysis 现在可以提供超过 1080p 的图像。Logging API 可以更详细的调试日志并改善了错误报告。Coordinate Transformation API 可以将不同用例间的坐标关联起来,如果您在 imageAnalysis 缓冲区中定位了兴趣点,便可以方便地在图像捕捉的输出或预览中轻松找到它。您可以使用 CameraFilter API 来指定详细的规则以选择合适的相机。如果应用只需要前置或者后置相机,可以使用 AvailableCamerasLimiter 来加快启动时间。CameraControllerInfo 中可提供相机功能的更多详细信息。
设备兼容性
CameraX 会持续关注设备兼容性,以便应用在众多设备上都能够良好运行。我们修复了很多诸如图像拉伸、缩放不正确、图像颠倒及关闭相机时意外输出了绿色图形等问题。每个 CameraX 的发布版本或补丁版本中都会添加此类修复,最新的稳定版为 1.0.2。
您可以在版本记录中看到每个版本中的详细变更,还可以在问题跟踪器中看已经修复的问题。
希望对 CameraX 1.1 版本的简要介绍对大家有所帮助,非常期待看到大家使用 CameraX 构建的功能!
原文标题:CameraX 1.1 有哪些新的特性发布?
文章出处:【微信公众号:谷歌开发者】欢迎添加关注!文章转载请注明出处。
审核编辑:汤梓红
-
Android
+关注
关注
12文章
3935浏览量
127339 -
相机
+关注
关注
4文章
1350浏览量
53581 -
设备
+关注
关注
2文章
4502浏览量
70598
原文标题:CameraX 1.1 有哪些新的特性发布?
文章出处:【微信号:Google_Developers,微信公众号:谷歌开发者】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论