使用 Camera2 API Kotlin 单击图像时出现白色图像

White image when clicking image using Camera2 API Kotlin

我们在代码中使用 Camera2 API 进行图像捕捉,每当我们在闪光灯模式开启的情况下捕捉图像时,我们都会在三星设备中获取白色图像。

下面是拍照的代码片段:

private val captureCallback = object : CameraCaptureSession.CaptureCallback() {
    override fun onCaptureCompleted(
        session: CameraCaptureSession,
        request: CaptureRequest,
        result: TotalCaptureResult
    ) {
        if (result != null) {
            process(result)
        }
    }

    private fun process(result: CaptureResult) {
        try {
            if (locked) return

            /* Wait for all states to be ready, if they are not ready repeat basic capture while camera is preparing for capture */
            if (result.isLocked() || captureTimes > MAX_CAPTURE_TIMES) {
                /* Take picture */
                locked = true
                capture()
            } else {
                /* Wait while camera is preparing */
                captureTimes++
                session?.capture(sessionBuilder?.build()!!, this, AsyncUtils.backgroundHandler)
            }
        } catch (t: Throwable) {
            pictureCallback?.onError(t)
        }
    }

    private fun capture() {
        cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE).apply {
            copyParamsFrom(sessionBuilder)
            /* Set picture quality */
            set(CaptureRequest.JPEG_QUALITY, config.pictureQuality.toByte())
            set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START)
            /* Add surface target that will receive capture */
            addTarget(imageReader?.surface!!)
            session?.apply {
                /* Freeze preview session */
                abortCaptures()
                stopRepeating()
                /* Take dat picture */
                capture(build(), null, AsyncUtils.backgroundHandler)
            }
        }
    }
}

我们在代码中使用 Camera2 API 进行图像捕捉,每当我们在闪光灯模式开启的情况下捕捉图像时,我们都会在三星设备中获取白色图像。

下面是拍照的代码片段:

private val stateCallback = object : CameraCaptureSession.StateCallback() {
    override fun onConfigured(cameraCaptureSession: CameraCaptureSession) {
        session = cameraCaptureSession
        try {
            sessionBuilder =
                cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
                    applyConfig(config)
                    addTarget(surface!!)
                }
            startSession()
            initCallback?.onActive()
            initCallback = null
        } catch (t: Throwable) {
            initCallback?.onError(t)
            initCallback = null
        }
    }

    override fun onConfigureFailed(cameraCaptureSession: CameraCaptureSession) {
        initCallback?.onError(CameraConfigurationFailedException)
        initCallback = null
    }
}

fun createInitialPreviewSession(textureView: TextureView, callback: InitCallback) {
    this.initCallback = callback
    createSession(textureView)
}

override fun createSession(textureView: TextureView) {
    try {
        initTextureViewSurface(textureView)
        initImageReader()
        cameraDevice.createCaptureSession(
            listOf(surface, imageReader?.surface),
            stateCallback,
            AsyncUtils.backgroundHandler
        )
    } catch (t: Throwable) {
        initCallback?.onError(t)
        initCallback = null
    }
}

我们在代码中使用 Camera2 API 进行图像捕捉,每当我们在闪光灯模式开启的情况下捕捉图像时,我们都会在三星设备中获取白色图像。

下面是拍照的代码片段:

private fun initImageReader() {
    this.imageReader = ImageReader.newInstance(
        config.pictureSize.width,
        config.pictureSize.height,
        ImageFormat.JPEG,
        2
    )
    imageReader?.setOnImageAvailableListener({ reader ->
        async(
            task = {
                val image = reader.acquireLatestImage()
                val bitmap = image.toBitmap()
                image.close()
                if (bitmap != null) {
                    val orientationDifference =
                        CameraUtils.calculateDisplayOrientation(activity, config).toFloat()
                    pictureTransformation?.transform(bitmap, config, orientationDifference)
                        ?: bitmap
                } else {
                    null
                }
            },
            onResult = {
                locked = false
                unlockFocus(config.focusMode)
                if (it != null) {
                    pictureCallback?.onPictureTaken(it)
                } else {
                    pictureCallback?.onError(PictureConversionException)
                }
            }
        )
    }, AsyncUtils.backgroundHandler)
}

fun takePicture(callback: PictureCallback) {
    captureTimes = 0
    this.pictureCallback = callback
    sessionBuilder?.apply {
        /* Trigger AF and AE */
        if (config.focusMode in arrayOf(
                FocusMode.AUTO,
                FocusMode.CONTINUOUS_PICTURE,
                FocusMode.CONTINUOUS_VIDEO
            )
        ) {
            set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
            focusCenterIfUnfocused()
        }
        if (config.isHardwareAtLeastLimited()) {
            set(
                CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
                CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START
            )
        }
        session?.capture(build(), captureCallback, AsyncUtils.backgroundHandler)
        if (config.isHardwareAtLeastLimited()) {
            set(
                CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
                CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE
            )
        }
    }
}

private fun focusCenterIfUnfocused() {
    if (isFocused()) return

    val activeRect =
        config.characteristics?.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)
            ?: return
    val centerX = activeRect.width() / 2
    val centerY = activeRect.height() / 2
    val offsetX = (activeRect.width() * 0.1f).toInt()
    val offsetY = (activeRect.height() * 0.1f).toInt()
    val centerRegion = Rect(
        max(centerX - offsetX, 0),
        max(centerY - offsetY, 0),
        min(centerX + offsetX, activeRect.width()),
        min(centerY + offsetY, activeRect.height())
    )
    sessionBuilder?.set(
        CaptureRequest.CONTROL_AF_REGIONS,
        arrayOf(MeteringRectangle(centerRegion, MeteringRectangle.METERING_WEIGHT_MAX - 1))
    )
}

private fun isFocused(): Boolean {
    val regions = sessionBuilder?.get(CaptureRequest.CONTROL_AF_REGIONS)
    val focusedRegion = regions?.getOrNull(0)
    return focusedRegion?.meteringWeight == MeteringRectangle.METERING_WEIGHT_MAX - 1
}

override fun release() {
    super.release()
    surface = null
    pictureCallback = null
    initCallback = null
    try {
        imageReader?.close()
    } catch (t: Throwable) {
    } finally {
        imageReader = null
    }
}

您有三个不同的代码片段,它们似乎根本无法组合在一起。

但请查看 https://github.com/googlearchive/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java 以获取闪光捕捉示例。