diff --git a/.idea/misc.xml b/.idea/misc.xml index 0ad17cb..55c0ec2 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,5 @@ - diff --git a/AICardDetector/build.gradle b/AICardDetector/build.gradle index 2634bbf..7bab25f 100644 --- a/AICardDetector/build.gradle +++ b/AICardDetector/build.gradle @@ -78,6 +78,9 @@ dependencies { implementation("com.google.accompanist:accompanist-permissions:0.33.2-alpha") + // Kotlin Coroutines + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") + diff --git a/AICardDetector/src/main/java/com/shahrukh/aicarddetector/libexposer/ObjectDetectionManagerFactory.kt b/AICardDetector/src/main/java/com/shahrukh/aicarddetector/libexposer/ObjectDetectionManagerFactory.kt index 5738e6c..82cbc0d 100644 --- a/AICardDetector/src/main/java/com/shahrukh/aicarddetector/libexposer/ObjectDetectionManagerFactory.kt +++ b/AICardDetector/src/main/java/com/shahrukh/aicarddetector/libexposer/ObjectDetectionManagerFactory.kt @@ -43,6 +43,9 @@ import kotlinx.coroutines.withContext import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException +import kotlin.coroutines.suspendCoroutine import kotlin.random.Random object ObjectDetectionManagerFactory { @@ -156,7 +159,7 @@ object ObjectDetectionManagerFactory { - fun capturePhoto( + /** fun capturePhoto( context: Context, // navController: NavController, cameraController: LifecycleCameraController, @@ -238,7 +241,83 @@ object ObjectDetectionManagerFactory { } } ) - } + }*/ + + suspend fun capturePhoto( + context: Context, + cameraController: LifecycleCameraController, + screenWidth: Float, + screenHeight: Float, + detections: List + ): Bitmap? = suspendCoroutine { continuation -> + cameraController.takePicture( + ContextCompat.getMainExecutor(context), + object : ImageCapture.OnImageCapturedCallback() { + + override fun onCaptureSuccess(image: ImageProxy) { + super.onCaptureSuccess(image) + Log.d("TAG", "onCaptureSuccess() called for capturePhoto") + + try { + val rotatedImageMatrix = Matrix().apply { + postRotate(image.imageInfo.rotationDegrees.toFloat()) + } + + // Convert the captured image to a Bitmap + val rotatedBitmap = Bitmap.createBitmap( + image.toBitmap(), + 0, + 0, + image.width, + image.height, + rotatedImageMatrix, + true + ) + + val detection = detections.firstOrNull() + if (detection != null) { + val croppedBitmap = cropImage( + rotatedBitmap, + detection.boundingBox, + detection.tensorImageWidth, + detection.tensorImageHeight + ) + + // Save cropped bitmap asynchronously + CoroutineScope(Dispatchers.IO).launch { + try { + saveBitmapToDevice(context, croppedBitmap) + withContext(Dispatchers.Main) { + continuation.resume(croppedBitmap) + } + } catch (e: Exception) { + Log.e("TAG", "Failed to save or process the image: $e") + withContext(Dispatchers.Main) { + continuation.resumeWithException(e) + } + } + } + } else { + Log.e("TAG", "No detection found.") + continuation.resume(null) + } + } catch (e: Exception) { + Log.e("TAG", "Exception in onCaptureSuccess: $e") + continuation.resumeWithException(e) + } finally { + image.close() + } + } + + override fun onError(exception: ImageCaptureException) { + super.onError(exception) + Log.e("TAG", "onError() called for capturePhoto with: exception = $exception") + continuation.resumeWithException(exception) + } + } + ) + } + diff --git a/app/src/main/java/com/shahrukh/aicarddetector/MainActivity.kt b/app/src/main/java/com/shahrukh/aicarddetector/MainActivity.kt index 0c0aaf6..15a276a 100644 --- a/app/src/main/java/com/shahrukh/aicarddetector/MainActivity.kt +++ b/app/src/main/java/com/shahrukh/aicarddetector/MainActivity.kt @@ -52,6 +52,9 @@ import com.shahrukh.aicarddetector.presentation.utils.Constants import com.shahrukh.aicarddetector.presentation.utils.Dimens import com.shahrukh.aicarddetector.presentation.utils.ImageScalingUtils import com.shahrukh.aicarddetector.ui.theme.AICardDetectorTheme +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch class MainActivity : ComponentActivity() { @@ -146,7 +149,7 @@ fun CardDetectorScreen() { .padding(top = Dimens.Padding8dp), verticalArrangement = Arrangement.SpaceAround ) { - ImageButton( + /** ImageButton( drawableResourceId = R.drawable.ic_capture, contentDescriptionResourceId = R.string.capture_button_description, modifier = Modifier @@ -170,9 +173,45 @@ fun CardDetectorScreen() { // Show toast of Save State } + )*/ + ImageButton( + drawableResourceId = R.drawable.ic_capture, + contentDescriptionResourceId = R.string.capture_button_description, + modifier = Modifier + .size(Dimens.CaptureButtonSize) + .clip(CircleShape) + .align(Alignment.CenterHorizontally) + .clickable { + // Ensure you have a CoroutineScope (e.g., lifecycleScope or a ViewModel scope) + cameraController?.let { + CoroutineScope(Dispatchers.Main).launch { + val croppedBitmap = ObjectDetectionManagerFactory.capturePhoto( + context = context, + cameraController = it, + screenWidth = screenWidth, + screenHeight = screenHeight, + detections = detections.value + ) + + croppedBitmap?.let { bitmap -> + // Use the cropped bitmap here, for example: + // Show it in a UI + // Save it to the device + Log.d("BitmapInfo", "Width: ${bitmap.width}, Height: ${bitmap.height}") + Log.d("BitmapInfo", "Config: ${bitmap.config}") + Log.d("BitmapInfo", "Byte Count: ${bitmap.allocationByteCount}") + + Toast.makeText(context, "Photo captured successfully!", Toast.LENGTH_SHORT).show() + } ?: run { + Toast.makeText(context, "Failed to capture photo.", Toast.LENGTH_SHORT).show() + } + } + } + } ) + } }