Skip to content

Commit

Permalink
QR code detection inside frame
Browse files Browse the repository at this point in the history
  • Loading branch information
rawatnaresh committed Jan 22, 2025
1 parent 55bdd97 commit 5cc012a
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 16 deletions.
40 changes: 37 additions & 3 deletions android/src/main/java/com/rncamerakit/CKCamera.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import kotlin.math.max
import kotlin.math.min
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.RectF
import com.facebook.react.uimanager.UIManagerHelper
import com.google.mlkit.vision.barcode.common.Barcode
Expand Down Expand Up @@ -307,9 +308,42 @@ class CKCamera(context: ThemedReactContext) : FrameLayout(context), LifecycleObs
val useCases = mutableListOf(preview, imageCapture)

if (scanBarcode) {
val analyzer = QRCodeAnalyzer { barcodes ->
if (barcodes.isNotEmpty()) {
onBarcodeRead(barcodes)
val analyzer = QRCodeAnalyzer { results ->
if (results.isNotEmpty()) {
val filteredResults = if (barcodeFrame !== null) {
results.filter { (barcode, imageSize) ->
val barcodeBoundingBox = barcode.boundingBox
if (barcodeBoundingBox === null) {
return@filter false
}

// val scaleX = viewFinder.width.toFloat() / imageSize.width
// val scaleY = viewFinder.height.toFloat() / imageSize.height

// Calculate scaling factors (image is always rotated by 90 degrees)
val scaleX = viewFinder.width.toFloat() / imageSize.height
val scaleY = viewFinder.height.toFloat() / imageSize.width
val scaledBarcodeBoundingBox = Rect(
(barcodeBoundingBox.left * scaleX).toInt(),
(barcodeBoundingBox.top * scaleY).toInt(),
(barcodeBoundingBox.right * scaleX).toInt(),
(barcodeBoundingBox.bottom * scaleY).toInt()
)

// Check if the scaled bounding box is within the frame rectangle
barcodeFrame?.frameRect!!.contains(scaledBarcodeBoundingBox)
}
} else {
// If no frame is defined, include all detected barcodes
results
}

// Extract only the barcodes
val barcodes = filteredResults.map { (barcode) -> barcode };

if (barcodes.isNotEmpty()) {
onBarcodeRead(barcodes)
}
}
}
imageAnalyzer!!.setAnalyzer(cameraExecutor, analyzer)
Expand Down
27 changes: 14 additions & 13 deletions android/src/main/java/com/rncamerakit/QRCodeAnalyzer.kt
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
package com.rncamerakit

import android.annotation.SuppressLint
import android.util.Size
import androidx.camera.core.ExperimentalGetImage
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.common.InputImage

class QRCodeAnalyzer (
private val onQRCodesDetected: (qrCodes: List<Barcode>) -> Unit
class QRCodeAnalyzer(
private val onQRCodesDetected: (qrCodes: List<Pair<Barcode, Size>>) -> Unit
) : ImageAnalysis.Analyzer {
@SuppressLint("UnsafeExperimentalUsageError")
@ExperimentalGetImage
override fun analyze(image: ImageProxy) {
val inputImage = InputImage.fromMediaImage(image.image!!, image.imageInfo.rotationDegrees)
val mediaImage = image.image ?: return

val inputImage = InputImage.fromMediaImage(mediaImage, image.imageInfo.rotationDegrees)

val scanner = BarcodeScanning.getClient()
scanner.process(inputImage)
.addOnSuccessListener { barcodes ->
val strBarcodes = mutableListOf<Barcode>()
barcodes.forEach { barcode ->
strBarcodes.add(barcode ?: return@forEach)
.addOnSuccessListener { barcodes ->
// Pair each barcode with the image dimensions
val result: List<Pair<Barcode, Size>> = barcodes.map { barcode -> barcode to Size(image.width, image.height) }
onQRCodesDetected(result)
}
.addOnCompleteListener {
image.close()
}
onQRCodesDetected(strBarcodes)
}
.addOnCompleteListener{
image.close()
}
}
}
}

0 comments on commit 5cc012a

Please sign in to comment.