Kotlin & Camera 2 中的 ImageReader - 从相机 reader 表面保存 .jpg 文件

ImageReader in Kotlin & Camera 2 - saving .jpg file from a camera reader surface

我正在尝试从我的 ImageReader.surface 中获取一张照片,我已将其添加为我的 CaptureSession 捕获请求的目标,我正在努力解决这个问题,因为我尝试使用 imageReader.acquireLatestImage() 但这个 alawys 将我引用到新 imagewriter.newInstance(...).dequeueinputimage 中的空对象枯萎,我在其中使用 ImageReader.surface 或者当我从 [=24 获取图像时=],这似乎是我的图像 reader 表面有问题,但我已经尝试了很多方法,但未能弄清楚如何在知道我在 reader ImageAVailablelistener:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.amjadshuk.roadanalysia, PID: 18251
java.lang.NullPointerException: Attempt to invoke virtual method 'android.media.Image$Plane[] android.media.Image.getPlanes()' on a null object reference
    at com.amjadshuk.roadanalysia.MainActivity.onCreate$lambda-14(MainActivity.kt:482)
    at com.amjadshuk.roadanalysia.MainActivity.$r8$lambda$NXtavG2wfAwvFvETtEdf5FaiLSE(Unknown Source:0)
    at com.amjadshuk.roadanalysia.MainActivity$$ExternalSyntheticLambda0.onImageAvailable(Unknown Source:2)
    at android.media.ImageReader$ListenerHandler.handleMessage(ImageReader.java:812)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:246)
    at android.app.ActivityThread.main(ActivityThread.java:8506)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1139)

我的全部代码:

   @RequiresApi(Build.VERSION_CODES.P)
fun camera3() {


    val handlerThread = HandlerThread("",HandlerThread.NORM_PRIORITY).apply {
        start()
    }
    val handler =  HandlerCompat.createAsync(handlerThread.looper).apply {
        post {
            //-----------------------------------------------------------------

            GlobalScope.launch {
                Looper.prepare()

                val cm = getSystemService(Context.CAMERA_SERVICE) as CameraManager

                val cc: CameraDevice.StateCallback = object : CameraDevice.StateCallback() {

                    @RequiresApi(Build.VERSION_CODES.Q)
                    override fun onOpened(cm: CameraDevice) {
                        findViewById<TextView>(R.id.textView29).text = "Camera 1 opened"


                        val surface1 = findViewById<SurfaceView>(R.id.surfaceView3).holder.surface


                        val cr = cm.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE).apply {


                            addTarget(surface1)
                            addTarget(imageReader.surface)

                        }.build()

                        val outputConfiguration = OutputConfiguration(surface1)
                        val outputConfiguration2 = OutputConfiguration(imageReader.surface)
                        val out = mutableListOf(outputConfiguration, outputConfiguration2)


                        cm.createCaptureSession(
                            SessionConfiguration(SessionConfiguration.SESSION_REGULAR,
                                out,
                                mainExecutor,
                                object : CameraCaptureSession.StateCallback() {
                                    override fun onConfigured(p0: CameraCaptureSession) {


                                        p0.setRepeatingRequest(
                                            cr, object : CameraCaptureSession.CaptureCallback() {

                                                override fun onCaptureCompleted(
                                                    session: CameraCaptureSession,
                                                    request: CaptureRequest,
                                                    result: TotalCaptureResult
                                                ) {
                                                    super.onCaptureCompleted(
                                                        session,
                                                        request,
                                                        result
                                                    )





                                                    Toast.makeText(applicationContext,"capture completed",Toast.LENGTH_SHORT).show()

                                                }
                                                                                                },
                                            null
                                        )

                                    }

                                    override fun onConfigureFailed(p0: CameraCaptureSession) {

                                    }

                                })
                        )
                    }

                    override fun onDisconnected(cm: CameraDevice) {


                    }

                    override fun onError(cm: CameraDevice, p1: Int) {


                    }


                }

                if (ActivityCompat.checkSelfPermission(
                        applicationContext,
                        Manifest.permission.CAMERA
                    ) != PackageManager.PERMISSION_GRANTED
                ) {


                    this@MainActivity.requestPermissions(arrayOf(Manifest.permission.CAMERA), 9998)


                }



                if (cm.cameraIdList.isNotEmpty()) {
                    cm.getCameraCharacteristics(cm.cameraIdList.first())
                        .get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
                    cm.openCamera(cm.cameraIdList.first(), mainExecutor, cc)
                }

                val cameraAccessException = CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED)
                cameraAccessException.printStackTrace()
                val message = cameraAccessException.message!!
                Log.e("camera2", "camera2: ${message}", cameraAccessException.fillInStackTrace())

                Looper.loop()
            }



        }
    }
        }

创建时:

 imageReader.setOnImageAvailableListener({

            it.acquireLatestImage().close()
        val image = imageReader.acquireLatestImage()
      val byteArray =   image.planes.last().buffer.array()
        val file = FileOutputStream(File.createTempFile("image",".jpg",filesDir))
        file.write(byteArray)

    },null)
            it.acquireLatestImage().close()
        val image = imageReader.acquireLatestImage()

如果此代码是您实际拥有的代码,则您正在获取最新的可用图像,然后立即将其关闭。然后您尝试立即获取另一张图像。那时相机不太可能生成第二张图像,因此您会返回 null

只需删除第一个 acquireLatestImage 行。