title: Image is already closed. CameraX Analyzer
body: <p>I am trying to convert the ProxyImage from the cameraX analyzer to Bitmap to analyze the images using Tensor Flow light. 
  So I implemented the cameraX Analyze call back which gives the image as proxyImage. That proxyImage i need to convert to bitmap.
  If I do this conversation on the UI thread, it makes the camera preview to lag. So I wanted to do it using Coroutines. 
  Now the problem is whenever I pass the proxyImage to coroutines to convert it to bitmap on the background thread it crashes with the IllegalStateException that "Image is already closed."</p>
  
  <pre><code>08-04 16:28:59.690 16185-16185/com.example.camerax E/libEGL: call to OpenGL ES API with no current context (logged once per thread)
  08-04 16:29:00.849 16185-16308/com.example.camerax E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
      Process: com.example.camerax, PID: 16185
      java.lang.IllegalStateException: Image is already closed
          at android.media.Image.throwISEIfImageIsInvalid(Image.java:68)
          at android.media.ImageReader$SurfaceImage$SurfacePlane.getBuffer(ImageReader.java:787)
          at androidx.camera.core.AndroidImageProxy$PlaneProxy.getBuffer(AndroidImageProxy.java:141)
          at com.example.camerax.MainActivity.getImageFromProxy(MainActivity.kt:216)
          at com.example.camerax.MainActivity.convertProxyImageToBitmap(MainActivity.kt:150)
          at com.example.camerax.MainActivity.access$convertProxyImageToBitmap(MainActivity.kt:38)
          at com.example.camerax.MainActivity$startCamera$3$1.invokeSuspend(MainActivity.kt:136)
          at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
          at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
          at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
          at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
          at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)
  </code></pre>
  
  <p>I think next frame is de referencing the previous frame while app is converting the proxyImage to bitmap in the background thread. 
  I read about the documentation and there they are saying that</p>
  
  <blockquote>
    <p>Upon return from this method, the image reference is closed.
    Therefore, the method should complete analysis or make a copy instead
    of passing the image reference beyond the analysis method.</p>
  </blockquote>
  
  <p>I am confused here that what it means by to make a copy of the image when we pass the image beyond the analysis method. 
  How I can handle this scenario. 
  Below is the code snippet. </p>
  
  <pre><code>  val imageAnalysisConfig = ImageAnalysisConfig.Builder()
              .setTargetResolution(Size(1280, 720))
              .build()
          val imageAnalysis = ImageAnalysis(imageAnalysisConfig)
          imageAnalysis.setAnalyzer { image: ImageProxy, _: Int -&gt;
  
              classifier = Classifier.create(this, Classifier.Model.FLOAT, Classifier.Device.CPU, 1)
  
              CoroutineScope(Default).launch {
                  convertProxyImageToBitmap(image)
              }
          }
  </code></pre>
  
  <p>Method to convert proxyImage to Bitmap. </p>
  
  <pre><code>private fun getImageFromProxy(image: ImageProxy): Bitmap {
  
          val yBuffer = image.planes[0].buffer // Y
          val uBuffer = image.planes[1].buffer // U
          val vBuffer = image.planes[2].buffer // V
          val ySize = yBuffer.remaining()
          val uSize = uBuffer.remaining()
          val vSize = vBuffer.remaining()
          val nv21 = ByteArray(ySize + uSize + vSize)
          //U and V are swapped
          yBuffer.get(nv21, 0, ySize)
          vBuffer.get(nv21, ySize, vSize)
          uBuffer.get(nv21, ySize + vSize, uSize)
          val yuvImage = YuvImage(nv21, ImageFormat.NV21, image.width, image.height, null)
          val out = ByteArrayOutputStream()
          yuvImage.compressToJpeg(Rect(0, 0, yuvImage.width, yuvImage.height), 100, out)
          val imageBytes = out.toByteArray()
          return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
      }
  </code></pre>
  
  <p>Thanks in advance for help.</p>