From 0f0045fadeadab4505ae77a8e8a7ffc1e86028c0 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Nicolas <6371790+pynicolas@users.noreply.github.com> Date: Tue, 12 May 2026 20:38:33 +0200 Subject: [PATCH] Capture/import image even when no document is detected --- .../fairscan/app/platform/ImageProcessor.kt | 33 +++++++++++++++---- .../app/ui/screens/camera/CameraScreen.kt | 5 ++- .../app/ui/screens/camera/CameraUiState.kt | 2 +- .../app/ui/screens/camera/CameraViewModel.kt | 19 ++++------- app/src/main/res/values-ar/strings.xml | 2 +- app/src/main/res/values-cs/strings.xml | 2 +- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-gl/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 2 +- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-tr/strings.xml | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- app/src/main/res/values-zh/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 17 files changed, 49 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/org/fairscan/app/platform/ImageProcessor.kt b/app/src/main/java/org/fairscan/app/platform/ImageProcessor.kt index 670ccae..85cfcd7 100644 --- a/app/src/main/java/org/fairscan/app/platform/ImageProcessor.kt +++ b/app/src/main/java/org/fairscan/app/platform/ImageProcessor.kt @@ -27,9 +27,13 @@ import org.fairscan.app.domain.Rotation import org.fairscan.app.ui.screens.settings.DefaultColorMode import org.fairscan.imageprocessing.ColorMode import org.fairscan.imageprocessing.Mask +import org.fairscan.imageprocessing.Point import org.fairscan.imageprocessing.Quad import org.fairscan.imageprocessing.autoColorMode +import org.fairscan.imageprocessing.createQuad import org.fairscan.imageprocessing.extractDocument +import org.fairscan.imageprocessing.resizeForMaxPixels +import org.fairscan.imageprocessing.rotate import org.fairscan.imageprocessing.scaledTo import org.opencv.android.Utils import org.opencv.core.Mat @@ -106,28 +110,43 @@ fun processedImage( fun extractDocumentFromBitmap( source: Bitmap, - quadInMask: Quad, + quadInMask: Quad?, rotationDegrees: Int, - mask: Mask, + mask: Mask?, viewModelScope: CoroutineScope, defaultColorMode: DefaultColorMode = DefaultColorMode.AUTO ): CapturedPage { val exportQuality = ExportQuality.BALANCED - val quad = quadInMask.scaledTo(mask.width, mask.height, source.width, source.height) + var colorMode = ColorMode.COLOR + var autoColorMode = colorMode + var normalizedQuad = createQuad(listOf( + Point(0.0, 0.0), Point(0.0, 1.0), Point(1.0, 1.0), Point(1.0, 0.0)) + ) + var page: Mat val rgba = Mat() Utils.bitmapToMat(source, rgba) val bgr = Mat() Imgproc.cvtColor(rgba, bgr, Imgproc.COLOR_RGBA2BGR) rgba.release() - val autoColorMode = autoColorMode(bgr, mask, quad) - val colorMode = defaultColorMode.colorMode ?: autoColorMode - val page = extractDocument(bgr, quad, rotationDegrees, colorMode, exportQuality.maxPixels) + + if (mask == null || quadInMask == null) { + // No document detected + val resized = resizeForMaxPixels(bgr, exportQuality.maxPixels.toDouble()) + page = rotate(resized, rotationDegrees) + resized.release() + } else { + val quad = quadInMask.scaledTo(mask.width, mask.height, source.width, source.height) + normalizedQuad = quad.scaledTo(source.width, source.height, 1, 1) + autoColorMode = autoColorMode(bgr, mask, quad) + colorMode = defaultColorMode.colorMode ?: autoColorMode + page = extractDocument(bgr, quad, rotationDegrees, colorMode, exportQuality.maxPixels) + } + val pageJpeg = Jpeg.fromMat(page, exportQuality.jpegQuality) bgr.release() page.release() - val normalizedQuad = quad.scaledTo(source.width, source.height, 1, 1) val baseRotation = Rotation.fromDegrees(rotationDegrees) val metadata = PageMetadata(normalizedQuad, baseRotation, autoColorMode) val sourceJpegDeferred = viewModelScope.async(Dispatchers.IO) { diff --git a/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraScreen.kt b/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraScreen.kt index 224043a..af5d984 100644 --- a/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraScreen.kt +++ b/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraScreen.kt @@ -16,7 +16,6 @@ package org.fairscan.app.ui.screens.camera import android.content.res.Configuration import android.util.Log -import androidx.activity.compose.BackHandler import androidx.camera.core.ImageProxy import androidx.camera.view.PreviewView import androidx.compose.animation.core.animateFloat @@ -526,7 +525,7 @@ private fun CameraPreviewWithOverlay( .background(Color.Black.copy(alpha = 0.6f)) ) } - if (cameraUiState.showDetectionError) { + if (cameraUiState.showCaptureError) { Box( modifier = Modifier .align(Alignment.Center) @@ -534,7 +533,7 @@ private fun CameraPreviewWithOverlay( .padding(16.dp) ) { Text( - text = stringResource(R.string.error_no_document), + text = stringResource(R.string.error_occurred), color = Color.White, fontSize = 16.sp ) diff --git a/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraUiState.kt b/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraUiState.kt index 14beb6d..adbf0bf 100644 --- a/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraUiState.kt +++ b/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraUiState.kt @@ -38,7 +38,7 @@ data class CameraUiState( val liveAnalysisState: LiveAnalysisState, val captureState: CaptureState, val importState: ImportState, - val showDetectionError: Boolean, + val showCaptureError: Boolean, val isLandscape: Boolean, val isDebugMode: Boolean, val isTorchEnabled: Boolean, diff --git a/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraViewModel.kt b/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraViewModel.kt index 3d46eec..6ebfda0 100644 --- a/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraViewModel.kt +++ b/app/src/main/java/org/fairscan/app/ui/screens/camera/CameraViewModel.kt @@ -154,19 +154,14 @@ class CameraViewModel(appContainer: AppContainer): ViewModel() { private suspend fun processCapturedImage( source: Bitmap, rotationDegrees: Int, - ): CapturedPage? = withContext(Dispatchers.IO) { - var result: CapturedPage? = null + ): CapturedPage = withContext(Dispatchers.IO) { val segmentation = imageSegmentationService.runSegmentationAndReturn(source) - if (segmentation != null) { - val mask = segmentation.segmentation - val originalSize = ImageSize(source.width, source.height) - val quad = detectDocumentQuad(mask, originalSize, isLiveAnalysis = false) - if (quad != null) { - val defaultColorMode = settingsRepository.defaultColorMode.first() - result = extractDocumentFromBitmap( - source, quad, rotationDegrees, mask, viewModelScope, defaultColorMode) - } - } + val mask = segmentation?.segmentation + val originalSize = ImageSize(source.width, source.height) + val quad = mask?.let { detectDocumentQuad(mask, originalSize, isLiveAnalysis = false) } + val defaultColorMode = settingsRepository.defaultColorMode.first() + val result = extractDocumentFromBitmap( + source, quad, rotationDegrees, mask, viewModelScope, defaultColorMode) return@withContext result } diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 073d40c..98dbb39 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -29,7 +29,7 @@ المزود: %1$s لم يعد من الممكن الوصول إلى مجلد التصدير المحدّد. يُرجى اختيار مجلد آخر. لم يُعثر على تطبيق لفتح هذا الملف - لم يكتشف أي مستند + حدث خطأ فشل حفظ الملف صدِّر صدِّر ك %1$s diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 395fabc..fc03e1c 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -29,7 +29,7 @@ Poskytovatel: %1$s Vybraná složka pro export již není dostupná. Vyberte prosím jinou složku. Nebyla nalezena žádná aplikace pro otevření tohoto souboru - Nebyl rozpoznán žádná dokument + Došlo k chybě Soubor se nepodařilo uložit Exportovat Exportovat jako %1$s diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 2375242..e1e0f2a 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -29,7 +29,7 @@ Anbieter: %1$s Der ausgewählte Exportordner ist nicht mehr zugänglich. Bitte wählen Sie einen anderen Ordner. Keine App zum Öffnen dieser Datei gefunden - Kein Dokument erkannt + Ein Fehler ist aufgetreten Datei konnte nicht gespeichert werden Exportieren Als %1$s exportieren diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 439d986..10a664c 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -29,7 +29,7 @@ Proveedor: %1$s La carpeta de exportación seleccionada ya no es accesible. Por favor, elija otra carpeta. No se encontró ninguna aplicación para abrir este archivo - No se detectó ningún documento + Se produjo un error No se pudo guardar el archivo Exportar Exportar como %1$s diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index a08c407..43e82f1 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -29,7 +29,7 @@ Fournisseur : %1$s Le dossier d’export sélectionné n’est plus accessible. Veuillez choisir un autre dossier. Aucune application trouvée pour ouvrir ce fichier - Aucun document détecté + Une erreur s’est produite Échec de l\'enregistrement du fichier Exporter Exporter en %1$s diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index acf6cfa..e1b3826 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -29,7 +29,7 @@ Provedor: %1$s O cartafol de exportación seleccionado xa non é accesible. Escolle outro cartafol. Non se atopou ningunha aplicación para abrir este ficheiro - Non se detectou ningún documento + Produciuse un erro Produciuse un erro ao gardar o ficheiro Exportar Exportar como %1$s diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 3005408..0778083 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -29,7 +29,7 @@ Provider: %1$s La cartella di esportazione selezionata non è più accessibile. Scegli un’altra cartella. Nessuna app trovata per aprire questo file - Nessun documento rilevato + Si è verificato un errore Impossibile salvare il file Esporta Esporta come %1$s diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 20669da..39f4b98 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -29,7 +29,7 @@ Provedor: %1$s A pasta de exportação selecionada não está mais acessível. Escolha outra pasta. Nenhum app encontrado para abrir este arquivo - Nenhum documento detectado + Ocorreu um erro Falha ao salvar o arquivo Exportar Exportar como %1$s diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index fe7f492..7196b87 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -29,7 +29,7 @@ Провайдер: %1$s Выбранная папка экспорта больше недоступна. Пожалуйста, выберите другую папку. Не найдено приложение для открытия этого файла - Документ не обнаружен + Произошла ошибка Не удалось сохранить файл Экспорт Экспортировать как %1$s diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 659a2c7..7c43e09 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -29,7 +29,7 @@ Sağlayıcı: %1$s Seçilen dışa aktarma dizini artık erişilebilir değil. Lütfen başka bir dizin seçin. No app found to open this file - No document detected + Bir hata oluştu Failed to save file Dışa aktar %1$s olarak dışa aktar diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index a8bb6f1..624c8ad 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -29,7 +29,7 @@ 提供者:%1$s 所選的匯出目錄已無法存取。請選擇其他目錄。 找不到可開啟此檔案的應用程式 - 未偵測到文件 + 發生錯誤 儲存檔案失敗 匯出 匯出為 %1$s diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 168ea9b..6b680e1 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -29,7 +29,7 @@ 提供方:%1$s 所选的导出目录已无法访问。请选择其他目录。 未找到可打开此文件的应用 - 未检测到任何文档 + 发生错误 无法保存文件 导出 导出为 %1$s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 50dfce7..adc2827 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -33,7 +33,7 @@ Failed to launch system file picker on this device Failed to set export directory No app found to open this file - No document detected + An error occurred Failed to save file Export Export as %1$s