New setting for default color mode ("default filter")
This commit is contained in:
@@ -25,6 +25,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.fairscan.app.ui.screens.camera.extractDocumentFromBitmap
|
||||
import org.fairscan.app.ui.screens.settings.DefaultColorMode
|
||||
import org.fairscan.imageprocessing.ImageSize
|
||||
import org.fairscan.imageprocessing.detectDocumentQuad
|
||||
import org.fairscan.imageprocessing.scaledTo
|
||||
@@ -62,7 +63,9 @@ class DocumentDetectionTest {
|
||||
if (quad != null) {
|
||||
val resizedQuad =
|
||||
quad.scaledTo(mask.width, mask.height, bitmap.width, bitmap.height)
|
||||
outputJpeg = extractDocumentFromBitmap(bitmap, resizedQuad, 0, mask, scope).pageJpeg
|
||||
val auto = DefaultColorMode.AUTO
|
||||
val page = extractDocumentFromBitmap(bitmap, resizedQuad,0, mask, scope, auto)
|
||||
outputJpeg = page.pageJpeg
|
||||
val file = File(context.getExternalFilesDir(null), imageFileName)
|
||||
file.writeBytes(outputJpeg.bytes)
|
||||
Log.i("DocumentDetectionTest", "Image saved to ${file.absolutePath}")
|
||||
|
||||
@@ -269,6 +269,7 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
SettingsScreen(
|
||||
settingsUiState,
|
||||
onDefaultColorModeChanged = { mode -> settingsViewModel.setDefaultColorMode(mode) },
|
||||
onChooseDirectoryClick = {
|
||||
try {
|
||||
launcher.launch(null)
|
||||
|
||||
@@ -195,6 +195,7 @@ class MainViewModel(val imageRepository: ImageRepository, launchMode: LaunchMode
|
||||
capturedPage.pageJpeg,
|
||||
sourceJpeg,
|
||||
capturedPage.metadata,
|
||||
capturedPage.colorMode,
|
||||
)
|
||||
imageRepository.pages()
|
||||
}
|
||||
|
||||
@@ -141,10 +141,10 @@ class ImageRepository(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun add(processed: Jpeg, source: Jpeg, metadata: PageMetadata) =
|
||||
suspend fun add(processed: Jpeg, source: Jpeg, metadata: PageMetadata, colorMode: ColorMode) =
|
||||
mutex.withLock {
|
||||
val id = "${System.currentTimeMillis()}"
|
||||
val key = PageViewKey(id, Rotation.R0, metadata.autoColorMode)
|
||||
val key = PageViewKey(id, Rotation.R0, colorMode)
|
||||
processedImageFile(key).writeBytes(processed.bytes)
|
||||
sourceFile(id).writeBytes(source.bytes)
|
||||
pages.addOrReplace(
|
||||
@@ -154,7 +154,7 @@ class ImageRepository(
|
||||
baseRotationDegrees = metadata.baseRotation.degrees,
|
||||
manualRotationDegrees = Rotation.R0.degrees,
|
||||
isColored = metadata.autoColorMode == ColorMode.COLOR,
|
||||
colorMode = metadata.autoColorMode,
|
||||
colorMode = colorMode,
|
||||
)
|
||||
)
|
||||
saveMetadata()
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
package org.fairscan.app.domain
|
||||
|
||||
import kotlinx.coroutines.Deferred
|
||||
import org.fairscan.imageprocessing.ColorMode
|
||||
|
||||
data class CapturedPage(
|
||||
val pageJpeg: Jpeg,
|
||||
val sourceJpeg: Deferred<Jpeg>,
|
||||
val metadata: PageMetadata,
|
||||
val colorMode: ColorMode,
|
||||
)
|
||||
|
||||
@@ -540,7 +540,8 @@ fun CameraScreenPreviewWithProcessedImage() {
|
||||
CapturedPage(
|
||||
debugImage("gallica.bnf.fr-bpt6k5530456s-1.jpg"),
|
||||
CompletableDeferred(Jpeg(ByteArray(0))),
|
||||
PageMetadata(quad, R0, ColorMode.COLOR))))
|
||||
PageMetadata(quad, R0, ColorMode.COLOR),
|
||||
ColorMode.COLOR)))
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 640, heightDp = 320)
|
||||
|
||||
@@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.fairscan.app.AppContainer
|
||||
@@ -35,6 +36,7 @@ import org.fairscan.app.domain.ExportQuality
|
||||
import org.fairscan.app.domain.Jpeg
|
||||
import org.fairscan.app.domain.PageMetadata
|
||||
import org.fairscan.app.domain.Rotation
|
||||
import org.fairscan.app.ui.screens.settings.DefaultColorMode
|
||||
import org.fairscan.imageprocessing.ImageSize
|
||||
import org.fairscan.imageprocessing.Mask
|
||||
import org.fairscan.imageprocessing.Quad
|
||||
@@ -53,6 +55,7 @@ sealed interface CameraEvent {
|
||||
class CameraViewModel(appContainer: AppContainer): ViewModel() {
|
||||
|
||||
private val imageSegmentationService = appContainer.imageSegmentationService
|
||||
private val settingsRepository = appContainer.settingsRepository
|
||||
private val logger = appContainer.logger
|
||||
|
||||
private val _events = MutableSharedFlow<CameraEvent>()
|
||||
@@ -165,8 +168,9 @@ class CameraViewModel(appContainer: AppContainer): ViewModel() {
|
||||
val quad = detectDocumentQuad(mask, originalSize, isLiveAnalysis = false)
|
||||
if (quad != null) {
|
||||
val resizedQuad = quad.scaledTo(mask.width, mask.height, source.width, source.height)
|
||||
val defaultColorMode = settingsRepository.defaultColorMode.first()
|
||||
result = extractDocumentFromBitmap(
|
||||
source, resizedQuad, rotationDegrees, mask, viewModelScope)
|
||||
source, resizedQuad, rotationDegrees, mask, viewModelScope, defaultColorMode)
|
||||
}
|
||||
}
|
||||
return@withContext result
|
||||
@@ -223,14 +227,20 @@ sealed class CaptureState {
|
||||
}
|
||||
|
||||
fun extractDocumentFromBitmap(
|
||||
source: Bitmap, quad: Quad, rotationDegrees: Int, mask: Mask, viewModelScope: CoroutineScope
|
||||
source: Bitmap,
|
||||
quad: Quad,
|
||||
rotationDegrees: Int,
|
||||
mask: Mask,
|
||||
viewModelScope: CoroutineScope,
|
||||
defaultColorMode: DefaultColorMode = DefaultColorMode.AUTO
|
||||
): CapturedPage {
|
||||
val rgba = Mat()
|
||||
Utils.bitmapToMat(source, rgba)
|
||||
val bgr = Mat()
|
||||
Imgproc.cvtColor(rgba, bgr, Imgproc.COLOR_RGBA2BGR) // CV_8UC4 → CV_8UC3
|
||||
rgba.release()
|
||||
val colorMode = autoColorMode(bgr, mask, quad)
|
||||
val autoColorMode = autoColorMode(bgr, mask, quad)
|
||||
val colorMode = defaultColorMode.colorMode ?: autoColorMode
|
||||
val maxPixels = ExportQuality.BALANCED.maxPixels
|
||||
val page = extractDocument(bgr, quad, rotationDegrees, colorMode, maxPixels)
|
||||
val pageJpeg = Jpeg.fromMat(page, ExportQuality.BALANCED.jpegQuality)
|
||||
@@ -239,11 +249,11 @@ fun extractDocumentFromBitmap(
|
||||
|
||||
val normalizedQuad = quad.scaledTo(source.width, source.height, 1, 1)
|
||||
val baseRotation = Rotation.fromDegrees(rotationDegrees)
|
||||
val metadata = PageMetadata(normalizedQuad, baseRotation, colorMode)
|
||||
val metadata = PageMetadata(normalizedQuad, baseRotation, autoColorMode)
|
||||
val sourceJpegDeferred = viewModelScope.async(Dispatchers.IO) {
|
||||
compressJpeg(source, 90)
|
||||
}
|
||||
return CapturedPage(pageJpeg, sourceJpegDeferred, metadata)
|
||||
return CapturedPage(pageJpeg, sourceJpegDeferred, metadata, colorMode)
|
||||
}
|
||||
|
||||
fun rotateBitmap(source: Bitmap, angle: Float): Bitmap {
|
||||
|
||||
@@ -22,16 +22,29 @@ import androidx.datastore.preferences.preferencesDataStore
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.fairscan.app.R
|
||||
import org.fairscan.app.domain.ExportQuality
|
||||
import org.fairscan.imageprocessing.ColorMode
|
||||
|
||||
private val Context.dataStore by preferencesDataStore(name = "fairscan_settings")
|
||||
|
||||
class SettingsRepository(private val context: Context) {
|
||||
|
||||
private val DEFAULT_COLOR_MODE = stringPreferencesKey("default_color_mode")
|
||||
private val EXPORT_DIR_URI = stringPreferencesKey("export_dir_uri")
|
||||
private val EXPORT_FORMAT = stringPreferencesKey("export_format")
|
||||
private val EXPORT_QUALITY = stringPreferencesKey("export_quality")
|
||||
|
||||
val defaultColorMode: Flow<DefaultColorMode> =
|
||||
context.dataStore.data.map { prefs ->
|
||||
when (prefs[DEFAULT_COLOR_MODE]) {
|
||||
"AUTO" -> DefaultColorMode.AUTO
|
||||
"COLOR" -> DefaultColorMode.COLOR
|
||||
"GRAYSCALE" -> DefaultColorMode.GRAYSCALE
|
||||
else -> DefaultColorMode.AUTO
|
||||
}
|
||||
}
|
||||
|
||||
val exportDirUri: Flow<String?> =
|
||||
context.dataStore.data.map { prefs ->
|
||||
prefs[EXPORT_DIR_URI]
|
||||
@@ -60,6 +73,12 @@ class SettingsRepository(private val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun setDefaultColorMode(mode: DefaultColorMode) {
|
||||
context.dataStore.edit { prefs ->
|
||||
prefs[DEFAULT_COLOR_MODE] = mode.name
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun setExportDirUri(uri: String?) {
|
||||
context.dataStore.edit { prefs ->
|
||||
if (uri == null) {
|
||||
@@ -83,6 +102,12 @@ class SettingsRepository(private val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
enum class DefaultColorMode(val colorMode: ColorMode?, val labelResource: Int) {
|
||||
AUTO(null, R.string.color_mode_auto),
|
||||
COLOR(ColorMode.COLOR, R.string.color_mode_color),
|
||||
GRAYSCALE(ColorMode.GRAYSCALE, R.string.color_mode_grayscale),
|
||||
}
|
||||
|
||||
enum class ExportFormat(val mimeType: String) {
|
||||
PDF("application/pdf"),
|
||||
JPEG("image/jpeg"),
|
||||
|
||||
@@ -54,6 +54,7 @@ import org.fairscan.app.ui.theme.FairScanTheme
|
||||
@Composable
|
||||
fun SettingsScreen(
|
||||
uiState: SettingsUiState,
|
||||
onDefaultColorModeChanged: (DefaultColorMode) -> Unit,
|
||||
onChooseDirectoryClick: () -> Unit,
|
||||
onResetExportDirClick: () -> Unit,
|
||||
onExportFormatChanged: (ExportFormat) -> Unit,
|
||||
@@ -71,6 +72,7 @@ fun SettingsScreen(
|
||||
) { paddingValues ->
|
||||
SettingsContent(
|
||||
uiState,
|
||||
onDefaultColorModeChanged,
|
||||
onChooseDirectoryClick,
|
||||
onResetExportDirClick,
|
||||
onExportFormatChanged,
|
||||
@@ -82,6 +84,7 @@ fun SettingsScreen(
|
||||
@Composable
|
||||
private fun SettingsContent(
|
||||
uiState: SettingsUiState,
|
||||
onDefaultColorModeChanged: (DefaultColorMode) -> Unit,
|
||||
onChooseDirectoryClick: () -> Unit,
|
||||
onResetExportDirClick: () -> Unit,
|
||||
onExportFormatChanged: (ExportFormat) -> Unit,
|
||||
@@ -108,6 +111,26 @@ private fun SettingsContent(
|
||||
.padding(20.dp)
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
Text(stringResource(R.string.settings_section_scan), style = MaterialTheme.typography.titleLarge)
|
||||
Spacer(Modifier.height(32.dp))
|
||||
|
||||
Text(stringResource(R.string.color_mode_default), style = MaterialTheme.typography.titleMedium)
|
||||
|
||||
DefaultColorMode.entries.forEach { mode ->
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
RadioButton(
|
||||
selected = uiState.defaultColorMode == mode,
|
||||
onClick = { onDefaultColorModeChanged(mode) },
|
||||
)
|
||||
Text(stringResource(mode.labelResource))
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(32.dp))
|
||||
|
||||
Text(stringResource(R.string.settings_section_export), style = MaterialTheme.typography.titleLarge)
|
||||
Spacer(Modifier.height(32.dp))
|
||||
|
||||
DirectorySettingItem(
|
||||
label = stringResource(R.string.export_directory),
|
||||
folderLabel,
|
||||
@@ -128,7 +151,7 @@ private fun SettingsContent(
|
||||
|
||||
Spacer(Modifier.height(32.dp))
|
||||
|
||||
Text(stringResource(R.string.export_quality), style = MaterialTheme.typography.titleLarge)
|
||||
Text(stringResource(R.string.export_quality), style = MaterialTheme.typography.titleMedium)
|
||||
|
||||
ExportQuality.entries.reversed().forEach { quality ->
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
@@ -142,7 +165,7 @@ private fun SettingsContent(
|
||||
|
||||
Spacer(Modifier.height(32.dp))
|
||||
|
||||
Text(stringResource(R.string.export_format), style = MaterialTheme.typography.titleLarge)
|
||||
Text(stringResource(R.string.export_format), style = MaterialTheme.typography.titleMedium)
|
||||
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
RadioButton(
|
||||
@@ -173,7 +196,7 @@ fun DirectorySettingItem(
|
||||
Column {
|
||||
Text(
|
||||
text = label,
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
|
||||
Spacer(Modifier.height(8.dp))
|
||||
@@ -209,13 +232,13 @@ fun DirectorySettingItem(
|
||||
@Preview
|
||||
@Composable
|
||||
fun SettingsScreenPreviewWithoutDir() {
|
||||
SettingsScreenPreview(SettingsUiState(null))
|
||||
SettingsScreenPreview(SettingsUiState())
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SettingsScreenPreviewWithDir() {
|
||||
SettingsScreenPreview(SettingsUiState("content://root/dir"))
|
||||
SettingsScreenPreview(SettingsUiState(exportDirUri = "content://root/dir"))
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -223,6 +246,7 @@ fun SettingsScreenPreview(uiState: SettingsUiState) {
|
||||
FairScanTheme {
|
||||
SettingsScreen(
|
||||
uiState,
|
||||
onDefaultColorModeChanged = {},
|
||||
onChooseDirectoryClick = {},
|
||||
onResetExportDirClick = {},
|
||||
onExportFormatChanged = {},
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.fairscan.app.AppContainer
|
||||
import org.fairscan.app.domain.ExportQuality
|
||||
|
||||
data class SettingsUiState(
|
||||
val defaultColorMode: DefaultColorMode = DefaultColorMode.AUTO,
|
||||
val exportDirUri: String? = null,
|
||||
val exportDirName: String? = null,
|
||||
val exportFormat: ExportFormat = ExportFormat.PDF,
|
||||
@@ -41,12 +42,14 @@ class SettingsViewModel(container: AppContainer) : ViewModel() {
|
||||
val dirName: StateFlow<String?> = _dirName
|
||||
|
||||
val uiState = combine(
|
||||
repo.defaultColorMode,
|
||||
repo.exportDirUri,
|
||||
dirName,
|
||||
repo.exportFormat,
|
||||
repo.exportQuality,
|
||||
) { uri, name, format, quality ->
|
||||
) { colorMode, uri, name, format, quality ->
|
||||
SettingsUiState(
|
||||
defaultColorMode = colorMode,
|
||||
exportDirUri = uri,
|
||||
exportDirName = name,
|
||||
exportFormat = format,
|
||||
@@ -58,6 +61,12 @@ class SettingsViewModel(container: AppContainer) : ViewModel() {
|
||||
SettingsUiState()
|
||||
)
|
||||
|
||||
fun setDefaultColorMode(pref: DefaultColorMode) {
|
||||
viewModelScope.launch {
|
||||
repo.setDefaultColorMode(pref)
|
||||
}
|
||||
}
|
||||
|
||||
fun setExportDirUri(uri: String?) {
|
||||
viewModelScope.launch {
|
||||
repo.setExportDirUri(uri)
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<string name="change_directory">غيّر المجلد</string>
|
||||
<string name="clear_text">امحُ النص</string>
|
||||
<string name="color_mode">فلتر</string>
|
||||
<string name="color_mode_auto">تلقائي</string>
|
||||
<string name="color_mode_color">ألوان</string>
|
||||
<string name="color_mode_default">الفلتر الافتراضي</string>
|
||||
<string name="color_mode_grayscale">تدرج الرمادي</string>
|
||||
<string name="contact">تواصل</string>
|
||||
<string name="copied_logs">نُسخت السجلات إلى الحافظة</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">مسح جديد</string>
|
||||
<string name="scan_in_progress">المسح قيد التقدم</string>
|
||||
<string name="settings">الإعدادات</string>
|
||||
<string name="settings_section_scan">المسح</string>
|
||||
<string name="settings_section_export">التصدير</string>
|
||||
<string name="share">شارك</string>
|
||||
<string name="share_document">شارك المستند</string>
|
||||
<string name="storage_permission_denied">تعذر حفظ الملف: رُفض الإذن</string>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<string name="change_directory">Změnit složku</string>
|
||||
<string name="clear_text">Smazat text</string>
|
||||
<string name="color_mode">Filtr</string>
|
||||
<string name="color_mode_auto">Automaticky</string>
|
||||
<string name="color_mode_color">Barva</string>
|
||||
<string name="color_mode_default">Výchozí filtr</string>
|
||||
<string name="color_mode_grayscale">Odstíny šedi</string>
|
||||
<string name="contact">Kontakt</string>
|
||||
<string name="copied_logs">Protokoly zkopírovány do schránky</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">Nové skenování</string>
|
||||
<string name="scan_in_progress">Probíhá skenování</string>
|
||||
<string name="settings">Nastavení</string>
|
||||
<string name="settings_section_scan">Skenování</string>
|
||||
<string name="settings_section_export">Export</string>
|
||||
<string name="share">Sdílet</string>
|
||||
<string name="share_document">Sdílet dokument</string>
|
||||
<string name="storage_permission_denied">Nelze uložit soubor: oprávnění bylo odmítnuto</string>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<string name="change_directory">Ordner ändern</string>
|
||||
<string name="clear_text">Text löschen</string>
|
||||
<string name="color_mode">Filter</string>
|
||||
<string name="color_mode_auto">Automatisch</string>
|
||||
<string name="color_mode_color">Farbe</string>
|
||||
<string name="color_mode_default">Standardfilter</string>
|
||||
<string name="color_mode_grayscale">Graustufen</string>
|
||||
<string name="contact">Kontakt</string>
|
||||
<string name="copied_logs">Logs in die Zwischenablage kopiert</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">Neuer Scan</string>
|
||||
<string name="scan_in_progress">Scan läuft</string>
|
||||
<string name="settings">Einstellungen</string>
|
||||
<string name="settings_section_scan">Scan</string>
|
||||
<string name="settings_section_export">Export</string>
|
||||
<string name="share">Teilen</string>
|
||||
<string name="share_document">Dokument teilen</string>
|
||||
<string name="storage_permission_denied">Datei kann nicht gespeichert werden: Berechtigung verweigert</string>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<string name="change_directory">Cambiar carpeta</string>
|
||||
<string name="clear_text">Borrar texto</string>
|
||||
<string name="color_mode">Filtro</string>
|
||||
<string name="color_mode_auto">Automático</string>
|
||||
<string name="color_mode_color">Color</string>
|
||||
<string name="color_mode_default">Filtro predeterminado</string>
|
||||
<string name="color_mode_grayscale">Escala de grises</string>
|
||||
<string name="contact">Contacto</string>
|
||||
<string name="copied_logs">Registros copiados al portapapeles</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">Nuevo escaneo</string>
|
||||
<string name="scan_in_progress">Escaneo en curso</string>
|
||||
<string name="settings">Ajustes</string>
|
||||
<string name="settings_section_scan">Escaneo</string>
|
||||
<string name="settings_section_export">Exportación</string>
|
||||
<string name="share">Compartir</string>
|
||||
<string name="share_document">Compartir documento</string>
|
||||
<string name="storage_permission_denied">No se puede guardar el archivo: permiso denegado</string>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<string name="change_directory">Changer de dossier</string>
|
||||
<string name="clear_text">Effacer le text</string>
|
||||
<string name="color_mode">Filtre</string>
|
||||
<string name="color_mode_auto">Automatique</string>
|
||||
<string name="color_mode_color">Couleur</string>
|
||||
<string name="color_mode_default">Filtre par défaut</string>
|
||||
<string name="color_mode_grayscale">Niveaux de gris</string>
|
||||
<string name="contact">Contact</string>
|
||||
<string name="copied_logs">Logs copiés dans le presse-papiers</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">Nouveau scan</string>
|
||||
<string name="scan_in_progress">Scan en cours</string>
|
||||
<string name="settings">Paramètres</string>
|
||||
<string name="settings_section_scan">Scan</string>
|
||||
<string name="settings_section_export">Export</string>
|
||||
<string name="share">Partager</string>
|
||||
<string name="share_document">Partager le document</string>
|
||||
<string name="storage_permission_denied">Impossible d’enregistrer le fichier : permission refusée</string>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<string name="change_directory">Trocar cartafol</string>
|
||||
<string name="clear_text">Borrar texto</string>
|
||||
<string name="color_mode">Filtro</string>
|
||||
<string name="color_mode_auto">Automático</string>
|
||||
<string name="color_mode_color">Cor</string>
|
||||
<string name="color_mode_default">Filtro predeterminado</string>
|
||||
<string name="color_mode_grayscale">Escala de grises</string>
|
||||
<string name="contact">Contacto</string>
|
||||
<string name="copied_logs">Rexistros copiados ao portapapeis</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">Novo escaneo</string>
|
||||
<string name="scan_in_progress">Escaneo en curso</string>
|
||||
<string name="settings">Configuración</string>
|
||||
<string name="settings_section_scan">Escaneo</string>
|
||||
<string name="settings_section_export">Exportación</string>
|
||||
<string name="share">Compartir</string>
|
||||
<string name="share_document">Compartir documento</string>
|
||||
<string name="storage_permission_denied">Non se pode gardar o ficheiro: permiso denegado</string>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<string name="change_directory">Cambia cartella</string>
|
||||
<string name="clear_text">Svuota testo</string>
|
||||
<string name="color_mode">Filtro</string>
|
||||
<string name="color_mode_auto">Automatico</string>
|
||||
<string name="color_mode_color">Colore</string>
|
||||
<string name="color_mode_default">Filtro predefinito</string>
|
||||
<string name="color_mode_grayscale">Scala di grigi</string>
|
||||
<string name="contact">Contatti</string>
|
||||
<string name="copied_logs">Log copiati negli appunti</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">Nuova scansione</string>
|
||||
<string name="scan_in_progress">Scansione in corso</string>
|
||||
<string name="settings">Impostazioni</string>
|
||||
<string name="settings_section_scan">Scansione</string>
|
||||
<string name="settings_section_export">Esportazione</string>
|
||||
<string name="share">Condividi</string>
|
||||
<string name="share_document">Condividi documento</string>
|
||||
<string name="storage_permission_denied">Impossibile salvare il file: permesso negato</string>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<string name="change_directory">Alterar diretório</string>
|
||||
<string name="clear_text">Limpar texto</string>
|
||||
<string name="color_mode">Filtro</string>
|
||||
<string name="color_mode_auto">Automático</string>
|
||||
<string name="color_mode_color">Cor</string>
|
||||
<string name="color_mode_default">Filtro padrão</string>
|
||||
<string name="color_mode_grayscale">Escala de cinza</string>
|
||||
<string name="contact">Contato</string>
|
||||
<string name="copied_logs">Registros copiados para a área de transferência</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">Nova digitalização</string>
|
||||
<string name="scan_in_progress">Digitalização em andamento</string>
|
||||
<string name="settings">Configurações</string>
|
||||
<string name="settings_section_scan">Digitalização</string>
|
||||
<string name="settings_section_export">Exportação</string>
|
||||
<string name="share">Compartilhar</string>
|
||||
<string name="share_document">Compartilhar documento</string>
|
||||
<string name="storage_permission_denied">Não foi possível salvar o arquivo: permissão negada</string>
|
||||
|
||||
@@ -8,10 +8,12 @@
|
||||
<string name="cancel">Отмена</string>
|
||||
<string name="change_directory">Изменить папку</string>
|
||||
<string name="clear_text">Стереть текст</string>
|
||||
<string name="color_mode">Фильтр</string>
|
||||
<string name="color_mode_auto">Автоматически</string>
|
||||
<string name="color_mode_color">Цвет</string>
|
||||
<string name="color_mode_default">Фильтр по умолчанию</string>
|
||||
<string name="color_mode_grayscale">Оттенки серого</string>
|
||||
<string name="contact">Контакты</string>
|
||||
<string name="color_mode">Фильтр</string>
|
||||
<string name="copied_logs">Журналы скопированы в буфер обмена</string>
|
||||
<string name="copy_logs">Копировать журналы</string>
|
||||
<string name="creating_export">Подготовка экспорта…</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">Начать</string>
|
||||
<string name="scan_in_progress">Сканирование выполняется</string>
|
||||
<string name="settings">Настройки</string>
|
||||
<string name="settings_section_scan">Сканирование</string>
|
||||
<string name="settings_section_export">Экспорт</string>
|
||||
<string name="share">Поделиться</string>
|
||||
<string name="share_document">Поделиться документом</string>
|
||||
<string name="storage_permission_denied">Невозможно сохранить файл: доступ запрещён</string>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<string name="change_directory">Dizini değiştir</string>
|
||||
<string name="clear_text">Metni temizle</string>
|
||||
<string name="color_mode">Filtre</string>
|
||||
<string name="color_mode_auto">Otomatik</string>
|
||||
<string name="color_mode_color">Renkli</string>
|
||||
<string name="color_mode_default">Varsayılan filtre</string>
|
||||
<string name="color_mode_grayscale">Gri tonlama</string>
|
||||
<string name="contact">İletişim</string>
|
||||
<string name="copied_logs">Günlükler panoya kopyalandı</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">Yeni Tarama</string>
|
||||
<string name="scan_in_progress">Tarama devam ediyor</string>
|
||||
<string name="settings">Ayarlar</string>
|
||||
<string name="settings_section_scan">Tarama</string>
|
||||
<string name="settings_section_export">Dışa aktarma</string>
|
||||
<string name="share">Paylaş</string>
|
||||
<string name="share_document">Belgeyi paylaş</string>
|
||||
<string name="storage_permission_denied">Dosya kaydedilemiyor: izin reddedildi</string>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<string name="change_directory">變更目錄</string>
|
||||
<string name="clear_text">清除文字</string>
|
||||
<string name="color_mode">濾鏡</string>
|
||||
<string name="color_mode_auto">自動</string>
|
||||
<string name="color_mode_color">彩色</string>
|
||||
<string name="color_mode_default">預設濾鏡</string>
|
||||
<string name="color_mode_grayscale">灰階</string>
|
||||
<string name="contact">聯絡我們</string>
|
||||
<string name="copied_logs">日誌已複製到剪貼簿</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">開始掃描</string>
|
||||
<string name="scan_in_progress">掃描進行中</string>
|
||||
<string name="settings">設定</string>
|
||||
<string name="settings_section_scan">掃描</string>
|
||||
<string name="settings_section_export">匯出</string>
|
||||
<string name="share">分享</string>
|
||||
<string name="share_document">分享文件</string>
|
||||
<string name="storage_permission_denied">無法儲存檔案:權限遭拒</string>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<string name="change_directory">更改目录</string>
|
||||
<string name="clear_text">清除文字</string>
|
||||
<string name="color_mode">滤镜</string>
|
||||
<string name="color_mode_auto">自动</string>
|
||||
<string name="color_mode_color">彩色</string>
|
||||
<string name="color_mode_default">默认滤镜</string>
|
||||
<string name="color_mode_grayscale">灰度</string>
|
||||
<string name="contact">联系人</string>
|
||||
<string name="copied_logs">日志已复制到剪贴板</string>
|
||||
@@ -58,6 +60,8 @@
|
||||
<string name="scan_button">新建扫描</string>
|
||||
<string name="scan_in_progress">正在进行扫描</string>
|
||||
<string name="settings">设置</string>
|
||||
<string name="settings_section_scan">扫描</string>
|
||||
<string name="settings_section_export">导出</string>
|
||||
<string name="share">共享</string>
|
||||
<string name="share_document">分享文档</string>
|
||||
<string name="storage_permission_denied">无法保存文件:权限被拒绝</string>
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
<string name="change_directory">Change folder</string>
|
||||
<string name="clear_text">Clear text</string>
|
||||
<string name="color_mode">Filter</string>
|
||||
<string name="color_mode_auto">Automatic</string>
|
||||
<string name="color_mode_color">Color</string>
|
||||
<string name="color_mode_default">Default filter</string>
|
||||
<string name="color_mode_grayscale">Grayscale</string>
|
||||
<string name="contact">Contact</string>
|
||||
<string name="copied_logs">Logs copied to clipboard</string>
|
||||
@@ -62,6 +64,8 @@
|
||||
<string name="scan_button">New Scan</string>
|
||||
<string name="scan_in_progress">Scan in progress</string>
|
||||
<string name="settings">Settings</string>
|
||||
<string name="settings_section_scan">Scan</string>
|
||||
<string name="settings_section_export">Export</string>
|
||||
<string name="share">Share</string>
|
||||
<string name="share_document">Share document</string>
|
||||
<string name="storage_permission_denied">Cannot save file: permission was denied</string>
|
||||
|
||||
@@ -75,7 +75,7 @@ class ImageRepositoryTest {
|
||||
val repo = repo()
|
||||
assertThat(repo.imageIds()).isEmpty()
|
||||
val jpeg = jpeg(101, 102, 103)
|
||||
repo.add(jpeg, jpeg(51), metadata1)
|
||||
repo.add(jpeg, jpeg(51), metadata1, COLOR)
|
||||
assertThat(repo.imageIds()).hasSize(1)
|
||||
val id = repo.imageIds()[0]
|
||||
val key = PageViewKey(id, R0, COLOR)
|
||||
@@ -96,7 +96,7 @@ class ImageRepositoryTest {
|
||||
fun delete_image() = runTest {
|
||||
val repo = repo()
|
||||
val jpeg = jpeg(101, 102, 103)
|
||||
repo.add(jpeg, jpeg(51), metadata1)
|
||||
repo.add(jpeg, jpeg(51), metadata1, COLOR)
|
||||
assertThat(jpegFiles(processedDir())).hasSize(1)
|
||||
assertThat(jpegFiles(sourceDir())).hasSize(1)
|
||||
assertThat(repo.imageIds()).hasSize(1)
|
||||
@@ -188,7 +188,7 @@ class ImageRepositoryTest {
|
||||
fun `clear should delete pages`() = runTest {
|
||||
val jpeg = jpeg(101, 102, 103)
|
||||
val repo1 = repo()
|
||||
repo1.add(jpeg, jpeg(51), metadata1)
|
||||
repo1.add(jpeg, jpeg(51), metadata1, COLOR)
|
||||
assertThat(repo1.imageIds()).isNotEmpty()
|
||||
repo1.clear()
|
||||
assertThat(repo1.imageIds()).isEmpty()
|
||||
@@ -201,7 +201,7 @@ class ImageRepositoryTest {
|
||||
@Test
|
||||
fun rotate() = runTest {
|
||||
val repo = repo()
|
||||
repo.add(jpeg(101, 102, 103), jpeg(51), metadata1)
|
||||
repo.add(jpeg(101, 102, 103), jpeg(51), metadata1, COLOR)
|
||||
assertThat(repo.pages().last().metadata).isEqualTo(metadata1)
|
||||
val id = repo.pages().last().id
|
||||
repo.rotate(id, true)
|
||||
@@ -230,9 +230,9 @@ class ImageRepositoryTest {
|
||||
@Test
|
||||
fun movePage() = runTest {
|
||||
val repo = repo()
|
||||
repo.add(jpeg(101), jpeg(51), metadata1)
|
||||
repo.add(jpeg(101), jpeg(51), metadata1, COLOR)
|
||||
Thread.sleep(1L) // to avoid file name clashes
|
||||
repo.add(jpeg(110), jpeg(51), metadata1)
|
||||
repo.add(jpeg(110), jpeg(51), metadata1, COLOR)
|
||||
val id0 = repo.imageIds().first()
|
||||
val id1 = repo.imageIds().last()
|
||||
repo.movePage(id1, 0)
|
||||
@@ -284,10 +284,10 @@ class ImageRepositoryTest {
|
||||
fun last_added_source_file() = runTest {
|
||||
val repo = repo()
|
||||
assertThat(repo.lastAddedSourceFile()).isNull()
|
||||
repo.add(jpeg(101), jpeg(51), metadata1)
|
||||
repo.add(jpeg(101), jpeg(51), metadata1, COLOR)
|
||||
assertThat(repo.lastAddedSourceFile()).hasBinaryContent(byteArrayOf(51))
|
||||
Thread.sleep(1)
|
||||
repo.add(jpeg(102), jpeg(52), metadata1)
|
||||
repo.add(jpeg(102), jpeg(52), metadata1, COLOR)
|
||||
assertThat(repo.lastAddedSourceFile()).hasBinaryContent(byteArrayOf(52))
|
||||
|
||||
val id = repo.imageIds().last()
|
||||
|
||||
Reference in New Issue
Block a user