diff --git a/app/src/main/java/org/mydomain/myscan/view/CameraPreview.kt b/app/src/main/java/org/mydomain/myscan/view/CameraPreview.kt index 463e8c4..a48ce80 100644 --- a/app/src/main/java/org/mydomain/myscan/view/CameraPreview.kt +++ b/app/src/main/java/org/mydomain/myscan/view/CameraPreview.kt @@ -46,6 +46,7 @@ import androidx.compose.ui.graphics.BlendMode import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.viewinterop.AndroidView @@ -149,17 +150,15 @@ fun bindCameraUseCases( } @Composable -fun AnalysisOverlay(liveAnalysisState: LiveAnalysisState) { +fun AnalysisOverlay(liveAnalysisState: LiveAnalysisState, debugMode: Boolean) { val binaryMask = liveAnalysisState.binaryMask if (binaryMask == null) { return } - val maskOverlay = replaceColor(binaryMask, Color.Black, Color.Transparent) Canvas(modifier = Modifier.fillMaxSize()) { - drawImage( - maskOverlay.scale(size.width.toInt(), size.height.toInt()).asImageBitmap(), - colorFilter = ColorFilter.tint(Color(0x8000FF00), BlendMode.SrcIn) - ) + if (debugMode) { + drawMask(this, binaryMask) + } if (liveAnalysisState.documentQuad != null) { val scaledQuad = liveAnalysisState.documentQuad.scaledTo( fromWidth = binaryMask.width, @@ -174,6 +173,15 @@ fun AnalysisOverlay(liveAnalysisState: LiveAnalysisState) { } } +private fun drawMask(drawScope: DrawScope, binaryMask: Bitmap) { + val maskOverlay = replaceColor(binaryMask, Color.Black, Color.Transparent) + val size = drawScope.size + drawScope.drawImage( + maskOverlay.scale(size.width.toInt(), size.height.toInt()).asImageBitmap(), + colorFilter = ColorFilter.tint(Color(0x8000FF00), BlendMode.SrcIn) + ) +} + fun replaceColor(bitmap: Bitmap, toReplace: Color, replacement: Color): Bitmap { val width = bitmap.width val height = bitmap.height diff --git a/app/src/main/java/org/mydomain/myscan/view/CameraScreen.kt b/app/src/main/java/org/mydomain/myscan/view/CameraScreen.kt index 6e3107f..4b09d74 100644 --- a/app/src/main/java/org/mydomain/myscan/view/CameraScreen.kt +++ b/app/src/main/java/org/mydomain/myscan/view/CameraScreen.kt @@ -86,6 +86,7 @@ data class CameraUiState( val liveAnalysisState: LiveAnalysisState, val captureState: CaptureState, val showDetectionError: Boolean, + val isDebugMode: Boolean ) const val CAPTURED_IMAGE_DISPLAY_DURATION = 1500L @@ -101,6 +102,7 @@ fun CameraScreen( var previewView by remember { mutableStateOf(null) } val pageIds by viewModel.pageIds.collectAsStateWithLifecycle() val thumbnailCoords = remember { mutableStateOf(Offset.Zero) } + var isDebugMode by remember { mutableStateOf(false) } val captureController = remember { CameraCaptureController() } DisposableEffect(Unit) { @@ -149,7 +151,12 @@ fun CameraScreen( { offset -> thumbnailCoords.value = offset } ) }, - cameraUiState = CameraUiState(pageIds.size, liveAnalysisState, captureState, showDetectionError), + cameraUiState = CameraUiState( + pageIds.size, + liveAnalysisState, + captureState, + showDetectionError, + isDebugMode), onCapture = { previewView?.bitmap?.let { Log.i("MyScan", "Pressed ") @@ -160,6 +167,7 @@ fun CameraScreen( } }, onFinalizePressed = onFinalizePressed, + onDebugModeSwitched = { isDebugMode = !isDebugMode }, thumbnailCoords = thumbnailCoords, ) } @@ -171,6 +179,7 @@ private fun CameraScreenScaffold( cameraUiState: CameraUiState, onCapture: () -> Unit, onFinalizePressed: () -> Unit, + onDebugModeSwitched: () -> Unit, thumbnailCoords: MutableState, ) { Box { @@ -180,6 +189,7 @@ private fun CameraScreenScaffold( pageList = pageList, pageCount = cameraUiState.pageCount, onFinalizePressed = onFinalizePressed, + onDebugModeSwitched = onDebugModeSwitched, ) } ) { innerPadding -> @@ -189,7 +199,9 @@ private fun CameraScreenScaffold( .fillMaxSize() ) { CameraPreviewWithOverlay(cameraPreview, cameraUiState) - MessageBox(cameraUiState.liveAnalysisState.inferenceTime) + if (cameraUiState.isDebugMode) { + MessageBox(cameraUiState.liveAnalysisState.inferenceTime) + } CaptureButton( onClick = onCapture, modifier = Modifier @@ -228,16 +240,16 @@ private fun CapturedImage(image: ImageBitmap, thumbnailCoords: MutableState - val bounds = coordinates.boundsInWindow() - val centerX = bounds.left + bounds.width / 2 - val centerY = bounds.top + bounds.height / 2 - with(density) { - targetOffsetX = thumbnailCoords.value.x - centerX - targetOffsetY = thumbnailCoords.value.y - centerY + .fillMaxHeight(0.8f) + .onGloballyPositioned { coordinates -> + val bounds = coordinates.boundsInWindow() + val centerX = bounds.left + bounds.width / 2 + val centerY = bounds.top + bounds.height / 2 + with(density) { + targetOffsetX = thumbnailCoords.value.x - centerX + targetOffsetY = thumbnailCoords.value.y - centerY + } } - } ) { Image( bitmap = image, @@ -309,7 +321,7 @@ private fun CameraPreviewWithOverlay( .height(height.dp) ) { cameraPreview() - AnalysisOverlay(cameraUiState.liveAnalysisState) + AnalysisOverlay(cameraUiState.liveAnalysisState, cameraUiState.isDebugMode) captureState.frozenImage?.let { Image( bitmap = it.asImageBitmap(), @@ -358,7 +370,25 @@ fun CameraScreenFooter( pageList: @Composable () -> Unit, pageCount: Int, onFinalizePressed: () -> Unit, + onDebugModeSwitched: () -> Unit, ) { + var tapCount by remember { mutableStateOf(0) } + var lastTapTime by remember { mutableStateOf(0L) } + val tapThreshold = 500L + val onPageCountClick = { + val currentTime = System.currentTimeMillis() + if (currentTime - lastTapTime < tapThreshold) { + tapCount++ + if (tapCount >= 3) { + onDebugModeSwitched() + tapCount = 0 + } + } else { + tapCount = 1 + } + lastTapTime = currentTime + } + Column (modifier = Modifier.background(MaterialTheme.colorScheme.primaryContainer)) { pageList() BottomAppBar( @@ -373,7 +403,8 @@ fun CameraScreenFooter( ) { Text( text = "$pageCount pages", - style = MaterialTheme.typography.bodyMedium + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.clickable(onClick = onPageCountClick) ) Button ( @@ -432,9 +463,10 @@ private fun ScreenPreview(captureState: CaptureState) { listState = LazyListState(), ) }, - cameraUiState = CameraUiState(pageCount = 4, LiveAnalysisState(), captureState, false), + cameraUiState = CameraUiState(pageCount = 4, LiveAnalysisState(), captureState, false, false), onCapture = {}, onFinalizePressed = {}, + onDebugModeSwitched = {}, thumbnailCoords = thumbnailCoords, ) }