Как исправить «розовый» захват изображения в Android Camera2API? - PullRequest
1 голос
/ 01 июля 2019

Я пытаюсь сделать снимок, используя 2 разных объектива (широкий и обычный).Предварительный просмотр отлично работает для обеих камер одновременно, используя новую поддержку мультикамер в Camera2API.Я использую Huawei Mate20Pro.Однако, когда я делаю снимок, он сохраняет только JPEG-изображения розового цвета.Но когда объект находится достаточно близко, картинка получается идеально.Вот что я имею в виду.Вот как выглядит розовый JPEG:

enter image description here

Однако, когда объект находится достаточно близко, захват выполняется хорошо.Вот как это выглядит: enter image description here

Вот основной код активности:

 button.setOnClickListener {
            if (isRunning) {
                handler.removeCallbacksAndMessages(null)
                restartActivity()
            } else {
                button.text = "Stop"
                handler.postDelayed(object : Runnable {
                    override fun run() {
                        twoLens.reset()
                        twoLens.isTwoLensShot = true
                        MainActivity.cameraParams.get(dualCamLogicalId).let {
                            if (it?.isOpen == true) {
                                Logd("In onClick. Taking Dual Cam Photo on logical camera: $dualCamLogicalId")
                                takePicture(this@MainActivity, it)
                                Toast.makeText(applicationContext, "Captured!", Toast.LENGTH_SHORT).show()
                            }
                        }
                        handler.postDelayed(this, 1000)
                    }
                }, 2000)
            }
            isRunning = !isRunning
        }
    }

Вот код захвата изображения.

fun captureStillPicture(activity: MainActivity, params: CameraParams) {
    if (!params.isOpen) {
        return
    }

    try {
        Logd("In captureStillPicture.")

        val camera = params.captureSession?.getDevice()

        if (null != camera) {
            params.captureBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
            params.captureBuilder?.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO)
if (params.id.equals(dualCamLogicalId) && twoLens.isTwoLensShot) {
val normalParams: CameraParams? = MainActivity.cameraParams.get(normalLensId)
val wideParams: CameraParams? = MainActivity.cameraParams.get(wideAngleId)
if (null == normalParams || null == wideParams)
        return
Logd("In captureStillPicture. This is a Dual Cam shot.")
params.captureBuilder?.addTarget(normalParams.imageReader?.surface!!)
             params.captureBuilder?.addTarget(wideParams.imageReader?.surface!!)
params.captureBuilder?.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 4)
params.captureBuilder?.set(CaptureRequest.JPEG_QUALITY, 100)
if (Build.VERSION.SDK_INT >= 28) {              params.captureBuilder?.set(CaptureRequest.DISTORTION_CORRECTION_MODE, CameraMetadata.DISTORTION_CORRECTION_MODE_OFF)
                //This is REQUIRED to disable HDR+ on Pixel 3 - even though Pixel 3 doesn't have sepia
                params.captureBuilder?.set(CaptureRequest.CONTROL_EFFECT_MODE, CameraMetadata.CONTROL_EFFECT_MODE_SEPIA)
            } else {
                //This is REQUIRED to disable HDR+ on Pixel 3 - even though Pixel 3 doesn't have sepia
                params.captureBuilder?.set(CaptureRequest.CONTROL_EFFECT_MODE, CameraMetadata.CONTROL_EFFECT_MODE_SEPIA)
                Logd("DUAL CAM DEBUG: I am setting sepia mode.")
//            Logd("DUAL CAM DEBUG: I am NOT setting sepia mode.")
            }
val rotation = activity.getWindowManager().getDefaultDisplay().getRotation()
            var capturedImageRotation = getOrientation(params, rotation)
            params.captureBuilder?.set(CaptureRequest.JPEG_ORIENTATION, capturedImageRotation)

            try {
                params.captureSession?.stopRepeating()
//                params.captureSession?.abortCaptures()
            } catch (e: CameraAccessException) {
                e.printStackTrace()
            }

            //Do the capture
            // TODO: Capture BURST HERE
if (28 <= Build.VERSION.SDK_INT)
params.captureSession?.captureSingleRequest(params.captureBuilder?.build(), params.backgroundExecutor, StillCaptureSessionCallback(activity, params))
else
params.captureSession?.capture(params.captureBuilder?.build(), StillCaptureSessionCallback(activity, params),
                    params.backgroundHandler)
        }
    } catch (e: CameraAccessException) {
        e.printStackTrace()

    } catch (e: IllegalStateException) {
        Logd("captureStillPicture IllegalStateException, aborting: " + e)
    }
}

Вот как я получаю захваченные изображения.

fun getImagesCaptured(activity: MainActivity, twoLens: TwoLensCoordinator){
    Logd("Normal image timestamp: " + twoLens.normalImage?.timestamp)
    Logd("Wide image timestamp: " + twoLens.wideImage?.timestamp)

    val wideBuffer: ByteBuffer? = twoLens.wideImage!!.planes[0].buffer
    val wideBytes = ByteArray(wideBuffer!!.remaining())
    wideBuffer.get(wideBytes)

    val normalBuffer: ByteBuffer? = twoLens.normalImage!!.planes[0].buffer
    val normalBytes = ByteArray(normalBuffer!!.remaining())
    normalBuffer.get(normalBytes)
    val options = BitmapFactory.Options()
    val wideMat: Mat = Mat(twoLens.wideImage!!.height, twoLens.wideImage!!.width, CvType.CV_8UC1)
    val tempWideBitmap = BitmapFactory.decodeByteArray(wideBytes, 0, wideBytes.size, options)

    val normalMat: Mat = Mat(twoLens.normalImage!!.height, twoLens.normalImage!!.width, CvType.CV_8UC1)
    val tempNormalBitmap = BitmapFactory.decodeByteArray(normalBytes, 0, normalBytes.size, options)
    save(normalBytes, "NormalShot")
    save(wideBytes, "WideShot")
}

Функция сохранения здесь.

fun save(bytes: Bitmap, tempName: String) {
    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
    val dataDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "TwoCameraImages")
    if (!dataDir.exists()) {
        dataDir.mkdir()
    }
    val fileName = tempName + "_IMG_$timeStamp.jpg"
    val fileDir = File(dataDir.path + File.separator + fileName)
    try {
        val fileOutputStream = FileOutputStream(fileDir)
        bytes.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream)
        //fileOutputStream.write(bytes)
        fileOutputStream.close()
    } catch (e: FileNotFoundException) {
        e.printStackTrace()
    } catch (e: IOException) {
        e.printStackTrace()
    }
}

Я построил поверх приведенного здесь кода: https://github.com/google/basicbokeh и переключился на задние камеры, и убрал расчеты лица.Но это розовое растровое изображение не уходит.Любая помощь?

...