关于CameraX是否可以打开多种特殊摄像头,例如广角、长焦、景深等等
虽然CameraSelector只简单定义了前置后置,没具体指明摄像头,但是可以跟Camera2 API的CameraCharacteristics结合使用,获取对应的cameraid,再传入CameraSelector中,最终实现cameraX打开特殊的摄像头。
CameraController与CameraProvider
两种方式都可以编写cameraX程序。前者较简单,后者可以实现更复杂需求。
当前demo开发基于CameraProvider,CameraController的待后面研究下。
CameraX实现预览
用ProcessCameraProvider去绑定多个usecase,usecase可以是预览、拍照,可以一次最多绑定三个usecase。创建预览的usecase时,需要用到Preview这个usecase,通过Preview.setSurfaceProvider将类型为SurfaceProvider传入,最终调用ProcessCameraProvider.bindToLifecycle绑定usecase时传入preview的usecase,这样就能接收预览数据了。
对于Preview,可以使用setTargetResolution与setTargetAspectRatio指定预览尺寸、预览比例,但是两者不能同时使用,若是使用setTargetAspectRatio,则会内部计算实际要设置的分辨率大小。
对于拍照的usecase,同样用setTargetResolution与setTargetAspectRatio,方法类似。
CameraX实现拍照
使用拍照的usecase类ImageCapture,配置时使用setTargetResolution指定拍照图片大小,最终调用ImageCapture.takePicture拍照。在ImageCapture.OnImageSavedCallback回调中,处理拍照回调。onImageSaved回调处理拍照完成回调。
CameraX实现触摸对焦
通过FocusMeteringAction.Builder传入对焦点坐标,构建一个对焦的action,然后再通过cameracontrol.startFocusAndMetering将这个action传入,(startFocusAndMetering执行的同时也会指定一个listener,该listener在对焦成功时、对焦取消时、对焦失败时会回调)去执行对焦动作。startFocusAndMetering返回值是ListenableFuture<FocusMeteringResult>,可以针对该返回值get().isFocusSuccessful()获取到对焦执行结果,get()是阻塞动作,需要等该动作。可以设置对焦的超时时间,超时时间到,底层会主动cancel对焦动作,默认是5s超时。底层执行cancel对焦最终也会回调到上文说的那个listener。
其与camera2实现该功能的对比,后者需要设置的参数较多。
CameraX实现持续对焦
CameraX没有跟camera2 API那样提供类似下面这种设置持续对焦的api。据说cameraX自动就做了持续对焦的事,而实际上在真机上面看也的确如此。
Camera2实现持续对焦的代码(拍照模式下):
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
CameraX的CaptureMode
拍照的usecase,imagecapture,在ImageCapture.builder里面提供setcapturemode接口,来设置拍照时基于拍照效率与拍照图片质量权衡的参数capturemode。
实际测试,ZSL是拍照效率最高的。如下图所示,同一场景同一机器同一时间三种不同capturemode的耗时。(测试环境,高通SM6475平台,后置4080*3060拍照尺寸)
CameraX实现AEAF锁定
经过确认,cameraX无api可以实现这个AEAF锁定。
不过对于锁AF,有间接的方法可以实现,以下是关键代码。
FocusMeteringAction focusAction = new FocusMeteringAction.Builder(
mPreviewView.getMeteringPointFactory().createPoint(x, y)).disableAutoCancel().build();
在之后mCameraControl.startFocusAndMetering(focusAction)触发对焦后,因为FocusMeteringAction.Builder.disableAutoCancel()的原因,使得af不会进行cancel,所以AF就间接锁住了。