ZXing, Android, JetPack Compose — нарисуйте ограничительную рамку вокруг QR-кодаAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 ZXing, Android, JetPack Compose — нарисуйте ограничительную рамку вокруг QR-кода

Сообщение Anonymous »

Я создаю сканер QR-кода с помощью Jetpack Compose в Android. Часть сканирования и считывание значений битов в QR-коде работают отлично и, как и ожидалось. Однако в рамках моего прототипа я хочу иметь возможность обводить QR-код красной рамкой.
В настоящее время я решаю две проблемы. Высота красного поля кажется правильной, но ширина слишком мала, и я не знаю почему. Вторая проблема заключается в том, что когда я перемещаю свой телефон, ограничивающая рамка перемещается повсюду и не привязана к реальному QR-коду. Я не знаю, как это исправить.
Изображение

Вот моя компонуемая функция CameraView...
@Composable
fun CameraPreview() {
val context = LocalContext.current
val scanner = MultiFormatReader().apply {
val hints: MutableMap = EnumMap(DecodeHintType::class.java)
hints[DecodeHintType.POSSIBLE_FORMATS] = listOf(BarcodeFormat.QR_CODE)
setHints(hints)
}

val qrCodeBounds = remember { mutableStateOf(null) }

BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
val screenWidth = maxWidth
val scanBoxSize = screenWidth * 0.6f // adjust the size of the scanning area here

AndroidView(
factory = { ctx ->
val previewView = PreviewView(ctx)
val cameraProviderFuture = ProcessCameraProvider.getInstance(ctx)
cameraProviderFuture.addListener({
val cameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
val imageAnalysis = ImageAnalysis.Builder()
.build()
.also {
it.setAnalyzer(ContextCompat.getMainExecutor(ctx)) { imageProxy ->
val result = scanQRCode(imageProxy, scanner)
imageProxy.close()
if (result != null) {
println("QR Code found: ${result.text}")
println("Image Proxy Width: ${imageProxy.width}, Height: ${imageProxy.height}")
qrCodeBounds.value = getBoundingBox(result.resultPoints, imageProxy.width, imageProxy.height, previewView.width, previewView.height)
} else {
qrCodeBounds.value = null
}
}
}

try {
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
context as ComponentActivity,
CameraSelector.DEFAULT_BACK_CAMERA,
preview,
imageAnalysis
)
} catch (exc: Exception) {
// Handle exceptions
}
}, ContextCompat.getMainExecutor(ctx))
previewView
},
modifier = Modifier.fillMaxSize()
)

Box(modifier = Modifier
.matchParentSize()
.background(Color.Black.copy(alpha = 0.8f))
)

// Scanning area box with a clear cutout
Box(
modifier = Modifier
.size(scanBoxSize)
.align(Alignment.Center)
.drawBehind {
// Draw a rounded clear rectangle to create a cutout effect
drawRoundRect(
color = Color.Transparent,
topLeft = Offset(0f, 0f),
size = Size(size.width, size.height),
cornerRadius = CornerRadius(x = 12.dp.toPx(), y = 12.dp.toPx()),
blendMode = BlendMode.Clear
)
}
.border(2.dp, MaterialTheme.colorScheme.onPrimary, RoundedCornerShape(12.dp))
)

qrCodeBounds.value?.let { bounds ->
Canvas(modifier = Modifier.fillMaxSize()) {
drawRect(
color = Color.Red,
topLeft = Offset(bounds.left.toFloat(), bounds.top.toFloat()),
size = Size(bounds.width().toFloat(), bounds.height().toFloat()),
style = Stroke(width = 3.dp.toPx())
)
}
}
}
}

Это моя функция getBoundingBox
private fun getBoundingBox(resultPoints: Array?, imageWidth: Int, imageHeight: Int, previewWidth: Int, previewHeight: Int): Rect? {
if (resultPoints == null || resultPoints.size != 4) {
return null
}

// Calculate scale factors
val scaleX = previewWidth.toFloat() / imageWidth
val scaleY = previewHeight.toFloat() / imageHeight

// Apply scale factors to the coordinates
val left = (resultPoints[0].x * scaleX).toInt()
val top = (resultPoints[0].y * scaleY).toInt()
val right = (resultPoints[2].x * scaleX).toInt()
val bottom = (resultPoints[2].y * scaleY).toInt()

return Rect(left, top, right, bottom)
}

А это моя функция scanQRCode
private fun scanQRCode(imageProxy: ImageProxy, scanner: MultiFormatReader): Result? {
val data = imageProxy.planes[0].buffer.let { buffer ->
val data = ByteArray(buffer.capacity())
buffer.get(data)
buffer.clear()
data
}
val source = PlanarYUVLuminanceSource(
data,
imageProxy.width,
imageProxy.height,
0,
0,
imageProxy.width,
imageProxy.height,
false
)
val binaryBitmap = BinaryBitmap(HybridBinarizer(source))
return try {
scanner.decodeWithState(binaryBitmap)
} catch (e: Exception) {
null // QR Code not found
}
}


Подробнее здесь: https://stackoverflow.com/questions/778 ... nd-qr-code
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»