如何使用 Android CameraX API 缩放相机?

Pat*_*kal 10 camera android zooming kotlin android-camerax

我尝试使用以下代码缩放相机CameraX

\n\n

首先,我得到一个Preview来自并尝试使用如下所示CameraX执行缩放。Preview

\n\n
var config = CameraX.getDefaultUseCaseConfig(PreviewConfig::class.java, lensFacing)\nvar preview = Preview(config)\npreview.zoom(zoom)\n
Run Code Online (Sandbox Code Playgroud)\n\n

preview.zoom()在我再次绑定并收到一些错误之后CameraX,它不起作用。

\n\n
CameraX.bindToLifecycle(this, preview, imageCapture, videoCapture)\n
Run Code Online (Sandbox Code Playgroud)\n\n

当上面的代码不起作用时,我CameraX.unbindAll()首先尝试使用,然后调用CameraX.bindToLifecycle(). 但再次遇到一些错误并且缩放没有成功。

\n\n

让我知道如何使用 API 缩放相机CameraX

\n\n
\n

更新错误日志如下:

\n
\n\n

仅使用错误日志CameraX.bindToLifecycle()

\n\n
java.lang.IllegalArgumentException: Exceeded max simultaneously bound image capture use cases.\n   at androidx.camera.camera2.impl.UseCaseSurfaceOccupancyManager.checkUseCaseLimitNotExceeded(UseCaseSurfaceOccupancyManager.java:61)\n   at androidx.camera.camera2.impl.Camera2DeviceSurfaceManager.getSuggestedResolutions(Camera2DeviceSurfaceManager.java:146)\n   at androidx.camera.core.CameraX.calculateSuggestedResolutions(CameraX.java:449)\n   at androidx.camera.core.CameraX.bindToLifecycle(CameraX.java:144)\n   at com.android.example.cameraxbasic.fragments.CameraFragment$updateCameraUi$2.onTouch(CameraFragment.kt:408)\n   at android.view.View.dispatchTouchEvent(View.java:12512)\n   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3032)\n   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)\n   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3032)\n   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)\n   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3032)\n   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)\n   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3032)\n   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)\n   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3032)\n   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)\n   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3032)\n   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)\n   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3032)\n   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)\n   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3032)\n   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)\n   at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:475)\n   at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1836)\n   at android.app.Activity.dispatchTouchEvent(Activity.java:3404)\n   at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)\n   at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:433)\n   at android.view.View.dispatchPointerEvent(View.java:12755)\n   at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5150)\n   at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4953)\n   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4470)\n   at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4523)\n   at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4489)\n   at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4629)\n   at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4497)\n   at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4686)\n   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4470)\n   at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4523)\n   at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4489)\n   at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4497)\n   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4470)\n   at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:7192)\n   at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:7126)\n   at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7087)\n   at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7295)\n   at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:193)\n   at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)\n   at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:184)\n   at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:7266)\n   at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:7318)\n   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)\n   at android.view.Choreographer.doCallbacks(Choreographer.java:761)\n   at android.view.Choreographer.doFrame(Choreographer.java:690)\n   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)\n   at android.os.Handler.handleCallback(Handler.java:873)\n   at android.os.Handler.dispatchMessage(Handler.java:99)\n   at android.os.Looper.loop(Looper.java:193)\n   at android.app.ActivityThread.main(ActivityThread.java:6912)\n   at java.lang.reflect.Method.invoke(Native Method)\n   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)\n   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:860)\n
Run Code Online (Sandbox Code Playgroud)\n\n

CameraX.unbindAll()使用和 的错误日志CameraX.bindToLifecycle()

\n\n
   E/Legacy-CameraDevice-JNI: getNativeWindow: Surface had no valid native window.\n   E/Legacy-CameraDevice-JNI: LegacyCameraDevice_nativeDetectSurfaceDimens: Could not retrieve native window from surface.\n\n--------- beginning of crash\n   2019-05-09 16:49:29.155 31123-31144/com.android.example.cameraxbasic E/AndroidRuntime: FATAL EXCEPTION: CameraX-\nProcess: com.android.example.cameraxbasic, PID: 31123\njava.lang.IllegalArgumentException: Surface was abandoned\n    at android.hardware.camera2.utils.SurfaceUtils.getSurfaceSize(SurfaceUtils.java:84)\n    at android.hardware.camera2.params.OutputConfiguration.<init>(OutputConfiguration.java:260)\n    at android.hardware.camera2.params.OutputConfiguration.<init>(OutputConfiguration.java:145)\n    at android.hardware.camera2.impl.CameraDeviceImpl.createCaptureSession(CameraDeviceImpl.java:518)\n    at androidx.camera.camera2.impl.CaptureSession.open(CaptureSession.java:196)\n    at androidx.camera.camera2.impl.Camera.openCaptureSession(Camera.java:535)\n    at androidx.camera.camera2.impl.Camera$StateCallback.onOpened(Camera.java:743)\n    at androidx.camera.core.CameraDeviceStateCallbacks$ComboDeviceStateCallback.onOpened(CameraDeviceStateCallbacks.java:99)\n    at android.hardware.camera2.impl.CameraDeviceImpl$1.run(CameraDeviceImpl.java:152)\n    at android.os.Handler.handleCallback(Handler.java:873)\n    at android.os.Handler.dispatchMessage(Handler.java:99)\n    at android.os.Looper.loop(Looper.java:193)\n    at android.os.HandlerThread.run(HandlerThread.java:65)\n Caused by: android.hardware.camera2.legacy.LegacyExceptionUtils$BufferQueueAbandonedException\n    at android.hardware.camera2.legacy.LegacyExceptionUtils.throwOnError(LegacyExceptionUtils.java:73)\n    at android.hardware.camera2.legacy.LegacyCameraDevice.getSurfaceSize(LegacyCameraDevice.java:606)\n    at android.hardware.camera2.utils.SurfaceUtils.getSurfaceSize(SurfaceUtils.java:82)\n    at android.hardware.camera2.params.OutputConfiguration.<init>(OutputConfiguration.java:260)\xc2\xa0\n    at android.hardware.camera2.params.OutputConfiguration.<init>(OutputConfiguration.java:145)\xc2\xa0\n    at android.hardware.camera2.impl.CameraDeviceImpl.createCaptureSession(CameraDeviceImpl.java:518)\xc2\xa0\n    at androidx.camera.camera2.impl.CaptureSession.open(CaptureSession.java:196)\xc2\xa0\n    at androidx.camera.camera2.impl.Camera.openCaptureSession(Camera.java:535)\xc2\xa0\n    at androidx.camera.camera2.impl.Camera$StateCallback.onOpened(Camera.java:743)\xc2\xa0\n    at androidx.camera.core.CameraDeviceStateCallbacks$ComboDeviceStateCallback.onOpened(CameraDeviceStateCallbacks.java:99)\xc2\xa0\n    at android.hardware.camera2.impl.CameraDeviceImpl$1.run(CameraDeviceImpl.java:152)\xc2\xa0\n    at android.os.Handler.handleCallback(Handler.java:873)\xc2\xa0\n    at android.os.Handler.dispatchMessage(Handler.java:99)\xc2\xa0\n    at android.os.Looper.loop(Looper.java:193)\xc2\xa0\n    at android.os.HandlerThread.run(HandlerThread.java:65)\xc2\xa0\n\n\n--------- beginning of system\n
Run Code Online (Sandbox Code Playgroud)\n

Pat*_*kal 15

最后,我们得到了CameraX中的Zoom API。请检查以下两种可用于缩放相机预览的方法。

捏合缩放:

val scaleGestureDetector = ScaleGestureDetector(context, listener)

cameraTextureView.setOnTouchListener { _, event ->
    scaleGestureDetector.onTouchEvent(event)
    return@setOnTouchListener true
}

val listener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
    override fun onScale(detector: ScaleGestureDetector): Boolean {
        val scale = cameraInfo.zoomRatio.value * detector.scaleFactor
        cameraControl.setZoomRatio(scale)
        return true
    }
}
Run Code Online (Sandbox Code Playgroud)

滑动缩放(使用搜索栏):

zoomSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {        
    override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
        cameraControl.setLinearZoom(progress / 100.toFloat())
    }

    override fun onStartTrackingTouch(seekBar: SeekBar?) {}

    override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
Run Code Online (Sandbox Code Playgroud)

使用下面的方法得到cameraControl

val cameraControl = CameraX.getCameraControl(lensFacing)
Run Code Online (Sandbox Code Playgroud)

代码参考链接: https://github.com/Pinkal7600/camera-samples/tree/master/CameraXBasic


lat*_*son 5

这就是我在最新的 CameraX 1.0.0-beta01 示例项目中所做的。添加到 onViewCreated 的底部

val listener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
override fun onScale(detector: ScaleGestureDetector): Boolean {
    val scale = camera!!.cameraInfo.zoomState.value!!.zoomRatio * detector.scaleFactor
        camera!!.cameraControl.setZoomRatio(scale)
        return true
    }
}

val scaleGestureDetector = ScaleGestureDetector(context, listener)

viewFinder.setOnTouchListener { _, event ->
    scaleGestureDetector.onTouchEvent(event)
    return@setOnTouchListener true
}
Run Code Online (Sandbox Code Playgroud)