如何使用ZXing和Android CameraX解码条形码和QR码。

6

如何集成ZXing库以便在新的Android Jetpack CameraX中使用它?

我知道我需要构建一个ImageAnalyzer,并在其中使用ZXing解码QR码条形码

1个回答

7

以下是我建立的ImageAnalyzer,用于完成这个任务:

class ZxingQrCodeAnalyzer(
    private val onQrCodesDetected: (qrCode: Result) -> Unit
) : ImageAnalysis.Analyzer {

  companion object {
    val reader = MultiFormatReader()
  }

  /*
      https://developer.android.com/training/camerax/configuration

      Default resolution: The default target resolution setting is 640x480.

      Adjusting both target resolution and corresponding aspect ratio will result
      in a best-supported resolution under 1080p (max analysis resolution).
  */
  override fun analyze(imageProxy: ImageProxy, rotationDegrees: Int) {
    // okay - manage rotation, not needed for QRCode decoding [-;
    // okay - manage it for barcode scanning instead!!!
    try {
      imageProxy.image?.let {
        // ImageProxy uses an ImageReader under the hood:
        // https://developer.android.com/reference/androidx/camera/core/ImageProxy.html
        // That has a default format of YUV_420_888 if not changed.
        // https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888
        // https://developer.android.com/reference/android/media/ImageReader.html
        if ((it.format == ImageFormat.YUV_420_888
            || it.format == ImageFormat.YUV_422_888
            || it.format == ImageFormat.YUV_444_888)
            && it.planes.size == 3) {
          val buffer = it.planes[0].buffer // We get the luminance plane only, since we
          // want to binarize it and we don't wanna take color into consideration.
          val bytes = ByteArray(buffer.capacity())
          buffer.get(bytes)
          // Create a LuminanceSource.
          val rotatedImage = RotatedImage(bytes, imageProxy.width, imageProxy.height)

          rotateImageArray(rotatedImage, rotationDegrees)

          val source = PlanarYUVLuminanceSource(rotatedImage.byteArray,
              rotatedImage.width,
              rotatedImage.height,
              0,
              0,
              rotatedImage.width,
              rotatedImage.height,
              false)

          // Create a Binarizer
          val binarizer = HybridBinarizer(source)
          // Create a BinaryBitmap.
          val binaryBitmap = BinaryBitmap(binarizer)
          // Try decoding...
          val result: Result
          try {
            result = reader.decode(binaryBitmap)
            onQrCodesDetected(result)
          } catch (e: NotFoundException) {
            e.printStackTrace()
          }
        } else {
          // Manage other image formats
          // TODO - https://developer.android.com/reference/android/media/Image.html
        }
      }
    } catch (ise: IllegalStateException) {
      ise.printStackTrace()
    }
  }

  // 90, 180. 270 rotation
  private fun rotateImageArray(imageToRotate: RotatedImage, rotationDegrees: Int) {
    if (rotationDegrees == 0) return // no rotation
    if (rotationDegrees % 90 != 0) return // only 90 degree times rotations

    val width = imageToRotate.width
    val height = imageToRotate.height

    val rotatedData = ByteArray(imageToRotate.byteArray.size)
    for (y in 0 until height) { // we scan the array by rows
      for (x in 0 until width) {
        when (rotationDegrees) {
          90 -> rotatedData[x * height + height - y - 1] =
              imageToRotate.byteArray[x + y * width] // Fill from top-right toward left (CW)
          180 -> rotatedData[width * (height - y - 1) + width - x - 1] =
              imageToRotate.byteArray[x + y * width] // Fill from bottom-right toward up (CW)
          270 -> rotatedData[y + x * height] =
                            imageToRotate.byteArray[y * width + width - x - 1] // The opposite (CCW) of 90 degrees
        }
      }
    }

    imageToRotate.byteArray = rotatedData

    if (rotationDegrees != 180) {
      imageToRotate.height = width
      imageToRotate.width = height
    }
  }
}

private data class RotatedImage(var byteArray: ByteArray, var width: Int, var height: Int)

我的CameraX ViewFinder没有渲染或显示任何内容。请帮忙解决。如果有Github链接将会很有用。 - Shubham Agrawal
@ShubhamAgrawal 你看过这个了吗?https://github.com/android/camera-samples - shadowsheep
我已经使用了CameraX,但是ZXing库无法工作。有没有帮助将这两个集成起来的方法? - Shubham Agrawal
代码运行良好,但问题出在前置摄像头上。当我尝试更改摄像头方向时,它没有响应。有什么帮助吗? - Shubham Agrawal
1
这是我找到的关于如何在结合CameraX和ZXing时调整图像旋转的唯一清晰示例。谢谢! - argenkiwi
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接