diff --git a/classic-components-example/build.gradle b/classic-components-example/build.gradle
index c3b0b6fa..d953f471 100644
--- a/classic-components-example/build.gradle
+++ b/classic-components-example/build.gradle
@@ -15,7 +15,7 @@ allprojects {
jvmToolchainVersion = 17
- scanbotSdkVersion = "8.1.0"
+ scanbotSdkVersion = "9.0.0.99-STAGING-SNAPSHOT"
androidCoreKtxVersion = "1.6.0"
constraintLayoutVersion = "2.0.4"
diff --git a/classic-components-example/document-enhancer/build.gradle b/classic-components-example/document-enhancer/build.gradle
new file mode 100644
index 00000000..c3414bb5
--- /dev/null
+++ b/classic-components-example/document-enhancer/build.gradle
@@ -0,0 +1,47 @@
+plugins {
+ id("com.android.application")
+ id("org.jetbrains.kotlin.android")
+}
+
+android {
+ namespace = project.ext.submodulesNamespace
+ compileSdk = project.ext.compileSdkVersion
+
+ defaultConfig {
+ applicationId = project.ext.exampleAppId
+ minSdk = project.ext.minSdkVersion
+ targetSdk = project.ext.targetSdkVersion
+ versionCode = 1
+ versionName = "1.0"
+ }
+
+ buildTypes {
+ named("debug") {
+ // set this to `false` to allow debugging and run a "non-release" build
+ minifyEnabled = false
+ debuggable = true
+ }
+ }
+
+ kotlin {
+ jvmToolchain(project.ext.jvmToolchainVersion)
+ }
+
+ packagingOptions {
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/NOTICE.txt'
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/DEPENDENCIES'
+ }
+
+ buildFeatures {
+ viewBinding = true
+ }
+}
+
+dependencies {
+ implementation(project(":common"))
+ implementation("io.scanbot:sdk-package-1:${project.ext.scanbotSdkVersion}")
+ implementation("androidx.appcompat:appcompat:${project.ext.androidxAppcompatVersion}")
+}
diff --git a/classic-components-example/document-enhancer/src/main/AndroidManifest.xml b/classic-components-example/document-enhancer/src/main/AndroidManifest.xml
new file mode 100755
index 00000000..4d1192e4
--- /dev/null
+++ b/classic-components-example/document-enhancer/src/main/AndroidManifest.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/classic-components-example/document-enhancer/src/main/java/io/scanbot/example/DocumentCameraActivity.kt b/classic-components-example/document-enhancer/src/main/java/io/scanbot/example/DocumentCameraActivity.kt
new file mode 100755
index 00000000..3800e7dc
--- /dev/null
+++ b/classic-components-example/document-enhancer/src/main/java/io/scanbot/example/DocumentCameraActivity.kt
@@ -0,0 +1,189 @@
+package io.scanbot.example
+
+import android.Manifest
+import android.content.pm.PackageManager
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Color
+import android.graphics.Matrix
+import android.os.Bundle
+import android.view.View
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+import androidx.core.view.WindowCompat
+import io.scanbot.common.onSuccess
+
+
+import io.scanbot.example.common.applyEdgeToEdge
+import io.scanbot.sdk.ScanbotSDK
+import io.scanbot.sdk.camera.CaptureInfo
+import io.scanbot.sdk.document.DocumentScannerFrameHandler
+import io.scanbot.sdk.document.ui.DocumentScannerView
+import io.scanbot.sdk.document.ui.IDocumentScannerViewCallback
+import io.scanbot.sdk.documentscanner.DocumentDetectionStatus
+import io.scanbot.sdk.documentscanner.DocumentEnhancer
+import io.scanbot.sdk.documentscanner.DocumentScanner
+import io.scanbot.sdk.documentscanner.DocumentStraighteningMode
+import io.scanbot.sdk.documentscanner.DocumentStraighteningParameters
+import io.scanbot.sdk.geometry.AspectRatio
+import io.scanbot.sdk.image.ImageRef
+import io.scanbot.sdk.process.ImageProcessor
+import io.scanbot.sdk.ui.camera.ShutterButton
+import io.scanbot.sdk.ui.view.base.configuration.CameraOrientationMode
+
+class DocumentCameraActivity : AppCompatActivity() {
+
+ private var lastUserGuidanceHintTs = 0L
+ private var flashEnabled = false
+ private var autoSnappingEnabled = true
+ private val ignoreOrientationMistmatch = true
+
+ private lateinit var documentScannerView: DocumentScannerView
+
+ private lateinit var resultView: ImageView
+ private lateinit var userGuidanceHint: TextView
+ private lateinit var autoSnappingToggleButton: Button
+ private lateinit var shutterButton: ShutterButton
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR_OVERLAY)
+
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_camera)
+ askPermission()
+ supportActionBar!!.hide()
+ applyEdgeToEdge(findViewById(R.id.root_view))
+
+ val scanbotSdk = ScanbotSDK(this)
+
+ documentScannerView = findViewById(R.id.document_scanner_view)
+
+ resultView = findViewById(R.id.result) as ImageView
+ val documentEnhancer = scanbotSdk.createDocumentEnhancer()
+ scanbotSdk.createDocumentScanner().onSuccess { documentScanner ->
+
+ documentScannerView.apply {
+ initCamera()
+ initScanningBehavior(
+ documentScanner,
+ { result, frame ->
+ // Here you are continuously notified about document scanning results.
+ // For example, you can show a user guidance text depending on the current scanning status.
+ result.onSuccess { data ->
+ }
+ false // typically you need to return false
+ },
+ object : IDocumentScannerViewCallback {
+ override fun onCameraOpen() {
+ documentScannerView.viewController.useFlash(flashEnabled)
+ }
+
+ override fun onPictureTaken(image: ImageRef, captureInfo: CaptureInfo) {
+ documentEnhancer.onSuccess { documentEnhancer ->
+ processPictureTaken(image, documentEnhancer)
+ }
+
+
+ // continue scanning
+ documentScannerView.postDelayed({
+ documentScannerView.viewController.startPreview()
+ }, 1000)
+ }
+ }
+ )
+ }
+ }
+
+ documentScannerView.polygonConfiguration.apply {
+ setPolygonFillColor(POLYGON_FILL_COLOR)
+ setPolygonFillColorOK(POLYGON_FILL_COLOR_OK)
+ }
+
+ documentScannerView.viewController.apply {
+ setAcceptedAngleScore(60.0)
+ setAcceptedSizeScore(75.0)
+ setIgnoreOrientationMismatch(ignoreOrientationMistmatch)
+
+ // Please note: https://docs.scanbot.io/document-scanner-sdk/android/features/document-scanner/autosnapping/#sensitivity
+ setAutoSnappingSensitivity(0.85f)
+ }
+
+ shutterButton = findViewById(R.id.shutterButton)
+ shutterButton.setOnClickListener { documentScannerView.viewController.takePicture(false) }
+ shutterButton.visibility = View.VISIBLE
+
+ findViewById(R.id.flashToggle).setOnClickListener {
+ flashEnabled = !flashEnabled
+ documentScannerView.viewController.useFlash(flashEnabled)
+ }
+
+ autoSnappingToggleButton = findViewById(R.id.autoSnappingToggle)
+ autoSnappingToggleButton.setOnClickListener {
+ autoSnappingEnabled = !autoSnappingEnabled
+ setAutoSnapEnabled(autoSnappingEnabled)
+ }
+ autoSnappingToggleButton.post { setAutoSnapEnabled(autoSnappingEnabled) }
+ }
+
+ private fun askPermission() {
+ if (ContextCompat.checkSelfPermission(
+ this,
+ Manifest.permission.CAMERA
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
+ ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 999)
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ documentScannerView.viewController.onResume()
+ }
+
+ override fun onPause() {
+ super.onPause()
+ documentScannerView.viewController.onPause()
+ }
+
+ private fun processPictureTaken(image: ImageRef, documentEnhancer: DocumentEnhancer) {
+ // STRAIGHTEN SCANNED IMAGE ASSUMING DOCUMENT IS BENT
+ // Run document enhancer unwarping on original image:
+ val result = documentEnhancer.straighten(image, DocumentStraighteningParameters().apply {
+ straighteningMode = DocumentStraighteningMode.STRAIGHTEN
+ // uncomment if you want wo set specific aspect ratios for documents
+ // aspectRatios = listOf(AspectRatio(29.0, 21.0))
+ }).getOrNull()
+
+ resultView.post {
+ resultView.setImageBitmap(
+ result?.straightenedImage?.toBitmap()?.getOrNull()
+ )
+ }
+ }
+
+ private fun setAutoSnapEnabled(enabled: Boolean) {
+ documentScannerView.viewController.apply {
+ autoSnappingEnabled = enabled
+ isFrameProcessingEnabled = enabled
+ }
+ documentScannerView.polygonConfiguration.setPolygonViewVisible(enabled)
+
+ autoSnappingToggleButton.text = "Automatic ${if (enabled) "ON" else "OFF"}"
+ if (enabled) {
+ shutterButton.showAutoButton()
+ } else {
+ shutterButton.showManualButton()
+ userGuidanceHint.visibility = View.GONE
+ }
+ }
+
+ companion object {
+ private val POLYGON_FILL_COLOR = Color.parseColor("#55ff0000")
+ private val POLYGON_FILL_COLOR_OK = Color.parseColor("#4400ff00")
+ }
+}
diff --git a/classic-components-example/document-enhancer/src/main/java/io/scanbot/example/ExampleApplication.kt b/classic-components-example/document-enhancer/src/main/java/io/scanbot/example/ExampleApplication.kt
new file mode 100755
index 00000000..d366bec5
--- /dev/null
+++ b/classic-components-example/document-enhancer/src/main/java/io/scanbot/example/ExampleApplication.kt
@@ -0,0 +1,55 @@
+package io.scanbot.example
+
+import android.app.Application
+import io.scanbot.sdk.ScanbotSDK
+import io.scanbot.sdk.ScanbotSDKInitializer
+import io.scanbot.sdk.util.log.LoggerProvider
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+import kotlin.coroutines.CoroutineContext
+
+class ExampleApplication : Application(), CoroutineScope {
+
+ private var job: Job = Job()
+ override val coroutineContext: CoroutineContext
+ get() = Dispatchers.IO + job
+
+ /*
+ * TODO 1/2: Add the Scanbot SDK license key here.
+ * Please note: The Scanbot SDK will run without a license key for one minute per session!
+ * After the trial period is over all Scanbot SDK functions as well as the UI components will stop working.
+ * You can get an unrestricted "no-strings-attached" 30 day trial license key for free.
+ * Please submit the trial license form (https://scanbot.io/trial/) on our website by using
+ * the app identifier "io.scanbot.example.sdk.android" of this example app.
+ */
+ val licenseKey = ""
+
+ override fun onCreate() {
+ super.onCreate()
+
+ ScanbotSDKInitializer()
+ .withLogging(true)
+ // TODO 2/2: Enable the Scanbot SDK license key
+ //.license(this, licenseKey)
+ .licenseErrorHandler { status, feature, statusMessage ->
+ LoggerProvider.logger.d("ExampleApplication", "+++> License status: ${status.name}. Status message: $statusMessage")
+ LoggerProvider.logger.d("ExampleApplication", "+++> Feature not available: ${feature.name}")
+ }
+ //.sdkFilesDirectory(this, getExternalFilesDir(null)!!)
+ .initialize(this)
+
+ LoggerProvider.logger.d("ExampleApplication", "Scanbot SDK was initialized")
+
+ val licenseInfo = ScanbotSDK(this).licenseInfo
+ LoggerProvider.logger.d("ExampleApplication", "License status: ${licenseInfo.status}")
+ LoggerProvider.logger.d("ExampleApplication", "License isValid: ${licenseInfo.isValid}")
+ LoggerProvider.logger.d("ExampleApplication", "License expirationDate: ${licenseInfo.expirationDateString}")
+
+ launch {
+ // Clear all previously created documents in storage
+ ScanbotSDK(this@ExampleApplication).documentApi.deleteAllDocuments()
+ }
+ }
+}
diff --git a/classic-components-example/document-enhancer/src/main/java/io/scanbot/example/MainActivity.kt b/classic-components-example/document-enhancer/src/main/java/io/scanbot/example/MainActivity.kt
new file mode 100644
index 00000000..c54eeb4e
--- /dev/null
+++ b/classic-components-example/document-enhancer/src/main/java/io/scanbot/example/MainActivity.kt
@@ -0,0 +1,119 @@
+package io.scanbot.example
+
+import android.Manifest
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import androidx.activity.result.PickVisualMediaRequest
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.lifecycleScope
+import io.scanbot.common.onSuccess
+
+
+import io.scanbot.example.common.Const
+import io.scanbot.example.common.applyEdgeToEdge
+import io.scanbot.example.common.showToast
+import io.scanbot.example.databinding.ActivityMainBinding
+import io.scanbot.sdk.ScanbotSDK
+import io.scanbot.sdk.documentscanner.DocumentStraighteningMode
+import io.scanbot.sdk.documentscanner.DocumentStraighteningParameters
+import io.scanbot.sdk.image.ImageRef
+import io.scanbot.sdk.util.PolygonHelper
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+Ths example uses new SDK APIs presented in Scanbot SDK v.8.x.x
+Please, check the official documentation for more details:
+Result API https://docs.scanbot.io/android/document-scanner-sdk/detailed-setup-guide/result-api/
+ImageRef API https://docs.scanbot.io/android/document-scanner-sdk/detailed-setup-guide/image-ref-api/
+ */
+
+class MainActivity : AppCompatActivity() {
+
+ private val scanbotSdk: ScanbotSDK by lazy { ScanbotSDK(this) }
+
+ private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
+
+ private val requestCameraLauncher =
+ registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
+ if (isGranted) {
+ startActivity(Intent(this, DocumentCameraActivity::class.java))
+ } else {
+ this@MainActivity.showToast("Camera permission is required to run this example!")
+ }
+ }
+
+ private val selectGalleryImageResultLauncher =
+ registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
+ if (!scanbotSdk.licenseInfo.isValid) {
+ this@MainActivity.showToast("1-minute trial license has expired!")
+ Log.e(Const.LOG_TAG, "1-minute trial license has expired!")
+ return@registerForActivityResult
+ }
+
+ if (uri == null) {
+ showToast("Error obtaining selected image!")
+ Log.e(Const.LOG_TAG, "Error obtaining selected image!")
+ return@registerForActivityResult
+ }
+
+ lifecycleScope.launch { processImage(uri) }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(binding.root)
+ supportActionBar?.hide()
+ applyEdgeToEdge(findViewById(R.id.root_view))
+
+ binding.showDocScannerBtn.setOnClickListener {
+ requestCameraLauncher.launch(Manifest.permission.CAMERA)
+ }
+
+ binding.importImage.setOnClickListener {
+ selectGalleryImageResultLauncher.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
+ }
+ }
+
+ /** Imports a selected image as original image and performs auto document scanning on it. */
+ private suspend fun processImage(uri: Uri) {
+ withContext(Dispatchers.Main) {
+ binding.progressBar.visibility = View.VISIBLE
+ this@MainActivity.showToast("Importing page...")
+ }
+
+ val documentImage = withContext(Dispatchers.Default) {
+ // load the selected image
+ val image = contentResolver.openInputStream(uri)?.use { inputStream ->
+ ImageRef.fromInputStream(inputStream)
+ } ?: throw IllegalStateException("Cannot open input stream from URI: $uri")
+
+ // create a new Page object with given image as original image:
+ val document = scanbotSdk.documentApi.createDocument()
+ .getOrNull() //can be handled with .getOrThrow() if needed
+ val page =
+ document?.addPage(image)?.getOrNull() //can be handled with .getOrThrow() if needed
+
+ // run document scanning on the page image:
+ page?.apply(newStraighteningParameters = DocumentStraighteningParameters().apply {
+ straighteningMode = DocumentStraighteningMode.STRAIGHTEN
+ // uncomment if you want wo set specific aspect ratios for documents
+ // aspectRatios = listOf(AspectRatio(29.0, 21.0))
+ })
+ page?.documentImage
+ }
+
+ withContext(Dispatchers.Main) {
+ binding.progressBar.visibility = View.GONE
+
+ // present cropped page image:
+ binding.importResultImage.setImageBitmap(documentImage)
+ binding.importResultImage.visibility = View.VISIBLE
+ }
+ }
+}
diff --git a/classic-components-example/document-enhancer/src/main/res/layout/activity_camera.xml b/classic-components-example/document-enhancer/src/main/res/layout/activity_camera.xml
new file mode 100755
index 00000000..f059f4db
--- /dev/null
+++ b/classic-components-example/document-enhancer/src/main/res/layout/activity_camera.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/classic-components-example/document-enhancer/src/main/res/layout/activity_main.xml b/classic-components-example/document-enhancer/src/main/res/layout/activity_main.xml
new file mode 100755
index 00000000..638005e1
--- /dev/null
+++ b/classic-components-example/document-enhancer/src/main/res/layout/activity_main.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/classic-components-example/document-enhancer/src/main/res/menu/menu_main.xml b/classic-components-example/document-enhancer/src/main/res/menu/menu_main.xml
new file mode 100755
index 00000000..8847389d
--- /dev/null
+++ b/classic-components-example/document-enhancer/src/main/res/menu/menu_main.xml
@@ -0,0 +1,6 @@
+
diff --git a/classic-components-example/document-enhancer/src/main/res/mipmap-hdpi/icon.png b/classic-components-example/document-enhancer/src/main/res/mipmap-hdpi/icon.png
new file mode 100755
index 00000000..cde69bcc
Binary files /dev/null and b/classic-components-example/document-enhancer/src/main/res/mipmap-hdpi/icon.png differ
diff --git a/classic-components-example/document-enhancer/src/main/res/mipmap-mdpi/icon.png b/classic-components-example/document-enhancer/src/main/res/mipmap-mdpi/icon.png
new file mode 100755
index 00000000..c133a0cb
Binary files /dev/null and b/classic-components-example/document-enhancer/src/main/res/mipmap-mdpi/icon.png differ
diff --git a/classic-components-example/document-enhancer/src/main/res/mipmap-xhdpi/icon.png b/classic-components-example/document-enhancer/src/main/res/mipmap-xhdpi/icon.png
new file mode 100755
index 00000000..bfa42f0e
Binary files /dev/null and b/classic-components-example/document-enhancer/src/main/res/mipmap-xhdpi/icon.png differ
diff --git a/classic-components-example/document-enhancer/src/main/res/mipmap-xxhdpi/icon.png b/classic-components-example/document-enhancer/src/main/res/mipmap-xxhdpi/icon.png
new file mode 100755
index 00000000..324e72cd
Binary files /dev/null and b/classic-components-example/document-enhancer/src/main/res/mipmap-xxhdpi/icon.png differ
diff --git a/classic-components-example/document-enhancer/src/main/res/values-w820dp/dimens.xml b/classic-components-example/document-enhancer/src/main/res/values-w820dp/dimens.xml
new file mode 100755
index 00000000..63fc8164
--- /dev/null
+++ b/classic-components-example/document-enhancer/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/classic-components-example/document-enhancer/src/main/res/values/dimens.xml b/classic-components-example/document-enhancer/src/main/res/values/dimens.xml
new file mode 100755
index 00000000..47c82246
--- /dev/null
+++ b/classic-components-example/document-enhancer/src/main/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
diff --git a/classic-components-example/document-enhancer/src/main/res/values/strings.xml b/classic-components-example/document-enhancer/src/main/res/values/strings.xml
new file mode 100755
index 00000000..21db9902
--- /dev/null
+++ b/classic-components-example/document-enhancer/src/main/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+ Scanbot SDK Example
+
+ Hello world!
+ Settings
+
diff --git a/classic-components-example/document-enhancer/src/main/res/values/styles.xml b/classic-components-example/document-enhancer/src/main/res/values/styles.xml
new file mode 100755
index 00000000..766ab993
--- /dev/null
+++ b/classic-components-example/document-enhancer/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/classic-components-example/settings.gradle.kts b/classic-components-example/settings.gradle.kts
index 36996292..4cc318dd 100755
--- a/classic-components-example/settings.gradle.kts
+++ b/classic-components-example/settings.gradle.kts
@@ -26,6 +26,7 @@ include(
":edit-polygon-view",
":camera-fragment",
":document-scanner",
+ ":document-enhancer",
":barcode-scanner",
":mrz-scanner",
":mc-scanner",
diff --git a/document-scanner-ready-to-use-ui-example/app/build.gradle b/document-scanner-ready-to-use-ui-example/app/build.gradle
index c42b895b..4b4f4c38 100644
--- a/document-scanner-ready-to-use-ui-example/app/build.gradle
+++ b/document-scanner-ready-to-use-ui-example/app/build.gradle
@@ -39,7 +39,7 @@ android {
}
}
-def scanbotSdkVersion = "8.1.0"
+def scanbotSdkVersion = "9.0.0.100-STAGING-SNAPSHOT"
dependencies {
diff --git a/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/DocumentDetectionSnippet.kt b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/DocumentDetectionSnippet.kt
index 3d5c380e..af9af00e 100644
--- a/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/DocumentDetectionSnippet.kt
+++ b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/DocumentDetectionSnippet.kt
@@ -44,7 +44,7 @@ class DocumentDetectionSnippet : AppCompatActivity() {
.forEach { image ->
if (image == null) {
Log.e(
- "StandaloneCropSnippet",
+ "DocumentDetectionSnippet",
"Failed to load image from URI"
)
return@forEach
diff --git a/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/DocumentQualityCheckSnippet.kt b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/DocumentQualityCheckSnippet.kt
index a2164c38..71cd214a 100644
--- a/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/DocumentQualityCheckSnippet.kt
+++ b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/DocumentQualityCheckSnippet.kt
@@ -16,6 +16,7 @@ import io.scanbot.common.onSuccess
import io.scanbot.sdk.ScanbotSDK
import io.scanbot.sdk.docprocessing.Document
import io.scanbot.sdk.documentqualityanalyzer.DocumentQuality
+import io.scanbot.sdk.documentqualityanalyzer.DocumentQualityAssessment
import io.scanbot.sdk.util.toImageRef
@@ -43,14 +44,14 @@ class DocumentQualityCheckSnippet : AppCompatActivity() {
.forEach { image ->
if (image == null) {
Log.e(
- "StandaloneCropSnippet",
+ "QualityCheckSnippet",
"Failed to load image from URI"
)
return@forEach
}
document.addPage(image)
}
- startCropping(document)
+ startDqa(document)
}
}
}
@@ -62,7 +63,7 @@ class DocumentQualityCheckSnippet : AppCompatActivity() {
// Create a document detector instance
val qualityAnalyzer = scanbotSDK.createDocumentQualityAnalyzer().getOrNull()
- fun startCropping(document: Document) {
+ fun startDqa(document: Document) {
document.pages.forEach { page ->
// Run quality check on the created page
val documentQuality =
@@ -76,13 +77,11 @@ class DocumentQualityCheckSnippet : AppCompatActivity() {
// @EndTag("Analyze the quality of a document image")
// Print the result.
- fun printResult(quality: DocumentQuality?) {
+ fun printResult(quality: DocumentQualityAssessment?) {
when (quality) {
- DocumentQuality.VERY_POOR -> print("The quality of the document is very poor")
- DocumentQuality.POOR -> print("The quality of the document is poor")
- DocumentQuality.REASONABLE -> print("The quality of the document is reasonable")
- DocumentQuality.GOOD -> print("The quality of the document is good")
- DocumentQuality.EXCELLENT -> print("The quality of the document is excellent")
+ DocumentQualityAssessment.ACCEPTABLE -> print("The quality of the document is good enough for processing.")
+ DocumentQualityAssessment.UNACCEPTABLE -> print("The quality of the document is not good enough for processing.")
+ DocumentQualityAssessment.UNCERTAIN -> print("The quality of the document is uncertain. It may be good enough for processing, but there is a risk that the result will not be good.")
else -> print("No document was found")
}
}
diff --git a/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/DocumentStraighteningSnippet.kt b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/DocumentStraighteningSnippet.kt
new file mode 100644
index 00000000..25aa77db
--- /dev/null
+++ b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/DocumentStraighteningSnippet.kt
@@ -0,0 +1,95 @@
+package com.example.scanbot.doc_code_snippet
+
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.lifecycleScope
+import com.example.scanbot.utils.getUrisFromGalleryResult
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import io.scanbot.common.onSuccess
+import io.scanbot.page.PageImageSource
+import io.scanbot.sdk.ScanbotSDK
+import io.scanbot.sdk.docprocessing.Document
+import io.scanbot.sdk.documentscanner.DocumentStraighteningMode
+import io.scanbot.sdk.documentscanner.DocumentStraighteningParameters
+import io.scanbot.sdk.geometry.AspectRatio
+import io.scanbot.sdk.util.isDefault
+import io.scanbot.sdk.util.toImageRef
+
+
+class DocumentStraighteningSnippet : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // In the real application, you should call this function on button click
+ importImagesFromLibrary()
+ }
+
+ private val scanbotSDK = ScanbotSDK(this@DocumentStraighteningSnippet)
+ private val context = this
+
+ private val pictureForDocDetectionResult =
+ this.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult ->
+ if (activityResult.resultCode == Activity.RESULT_OK) {
+ activityResult.data?.let { imagePickerResult ->
+ lifecycleScope.launch {
+ withContext(Dispatchers.Default) {
+ scanbotSDK.documentApi.createDocument().onSuccess { document ->
+ getUrisFromGalleryResult(imagePickerResult)
+ .asSequence() // process images one by one instead of collecting the whole list - less memory consumption
+ .map { it.toImageRef(contentResolver).getOrNull() }
+ .forEach { image ->
+ if (image == null) {
+ Log.e(
+ "StraighteningSnippet",
+ "Failed to load image from URI"
+ )
+ return@forEach
+ }
+ document.addPage(image)
+ }
+ startStraightening(document)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // @Tag("Direct Document straightening on page")
+ fun startStraightening(document: Document) {
+ document.pages.forEach { page ->
+ page.apply(
+ newStraighteningParameters = DocumentStraighteningParameters(
+ straighteningMode = DocumentStraighteningMode.STRAIGHTEN,
+ // Expected aspect ratios for the documents. Comment if unknown.
+ aspectRatios = listOf(AspectRatio(3.0, 4.0))
+ )
+ )
+ // Set the source of the page to IMPORTED if needs
+ page.source = PageImageSource.IMPORTED
+ }
+ }
+ // @EndTag("Direct Document straightening on page")
+
+ private fun importImagesFromLibrary() {
+ val imageIntent = Intent()
+ imageIntent.type = "image/*"
+ imageIntent.action = Intent.ACTION_GET_CONTENT
+ imageIntent.putExtra(Intent.EXTRA_LOCAL_ONLY, false)
+ imageIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false)
+ imageIntent.putExtra(
+ Intent.EXTRA_MIME_TYPES,
+ arrayOf("image/jpeg", "image/png", "image/webp", "image/heic")
+ )
+ pictureForDocDetectionResult.launch(Intent.createChooser(imageIntent, "Select Picture"))
+ }
+
+}
+
diff --git a/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/ImageQualityCheckSnippet.kt b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/ImageQualityCheckSnippet.kt
index 12d0605b..2d4a7684 100644
--- a/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/ImageQualityCheckSnippet.kt
+++ b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/ImageQualityCheckSnippet.kt
@@ -13,6 +13,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import io.scanbot.sdk.ScanbotSDK
import io.scanbot.sdk.documentqualityanalyzer.DocumentQuality
+import io.scanbot.sdk.documentqualityanalyzer.DocumentQualityAssessment
import io.scanbot.sdk.image.ImageRef
import io.scanbot.sdk.util.toImageRef
@@ -62,13 +63,11 @@ class ImageQualityCheckSnippet : AppCompatActivity() {
// @EndTag("Analyze the quality of an image")
// Print the result.
- fun printResult(quality: DocumentQuality?) {
+ fun printResult(quality: DocumentQualityAssessment?) {
when (quality) {
- DocumentQuality.VERY_POOR -> print("The quality of the document is very poor")
- DocumentQuality.POOR -> print("The quality of the document is poor")
- DocumentQuality.REASONABLE -> print("The quality of the document is reasonable")
- DocumentQuality.GOOD -> print("The quality of the document is good")
- DocumentQuality.EXCELLENT -> print("The quality of the document is excellent")
+ DocumentQualityAssessment.ACCEPTABLE -> print("The quality of the document is good enough for processing.")
+ DocumentQualityAssessment.UNACCEPTABLE -> print("The quality of the document is not good enough for processing.")
+ DocumentQualityAssessment.UNCERTAIN -> print("The quality of the document is uncertain. It may be good enough for processing, but there is a risk that the result will not be good.")
else -> print("No document was found")
}
}
diff --git a/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/ImageStraighteningSnippet.kt b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/ImageStraighteningSnippet.kt
new file mode 100644
index 00000000..3e66fe4e
--- /dev/null
+++ b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/ImageStraighteningSnippet.kt
@@ -0,0 +1,93 @@
+package com.example.scanbot.doc_code_snippet
+
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.lifecycleScope
+import com.example.scanbot.utils.getUrisFromGalleryResult
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import io.scanbot.common.onFailure
+import io.scanbot.common.onSuccess
+import io.scanbot.page.PageImageSource
+import io.scanbot.sdk.ScanbotSDK
+import io.scanbot.sdk.docprocessing.Document
+import io.scanbot.sdk.documentscanner.DocumentStraighteningMode
+import io.scanbot.sdk.documentscanner.DocumentStraighteningParameters
+import io.scanbot.sdk.geometry.AspectRatio
+import io.scanbot.sdk.image.ImageRef
+import io.scanbot.sdk.util.isDefault
+import io.scanbot.sdk.util.toImageRef
+
+
+class ImageStraighteningSnippet : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // In the real application, you should call this function on button click
+ importImagesFromLibrary()
+ }
+
+ private val scanbotSDK = ScanbotSDK(this@ImageStraighteningSnippet)
+ private val context = this
+
+ private val pictureForDocDetectionResult =
+ this.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult ->
+ if (activityResult.resultCode == RESULT_OK) {
+ activityResult.data?.let { imagePickerResult ->
+ lifecycleScope.launch {
+ withContext(Dispatchers.Default) {
+ getUrisFromGalleryResult(imagePickerResult)
+ .asSequence() // process images one by one instead of collecting the whole list - less memory consumption
+ .map { it.toImageRef(contentResolver).getOrNull() }
+ .forEach { image ->
+ if (image == null) {
+ Log.e(
+ "StraighteningSnippet",
+ "Failed to load image from URI"
+ )
+ return@forEach
+ }
+ startStraightening(image)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // @Tag("Direct Document straightening on image")
+ fun startStraightening(imageRef: ImageRef) {
+ scanbotSDK.createDocumentEnhancer().onSuccess { enhancer ->
+ val params = DocumentStraighteningParameters(
+ straighteningMode = DocumentStraighteningMode.STRAIGHTEN,
+ // Expected aspect ratios for the documents. Comment if unknown.
+ aspectRatios = listOf(AspectRatio(3.0, 4.0))
+ )
+ enhancer.straighten(imageRef, params).onSuccess { straightenedImage ->
+ // straightenedImage is an ImageRef of the straightened image, you can display it in the UI or save it to storage
+ }
+ }
+ }
+ // @EndTag("Direct Document straightening on image")
+
+ private fun importImagesFromLibrary() {
+ val imageIntent = Intent()
+ imageIntent.type = "image/*"
+ imageIntent.action = Intent.ACTION_GET_CONTENT
+ imageIntent.putExtra(Intent.EXTRA_LOCAL_ONLY, false)
+ imageIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false)
+ imageIntent.putExtra(
+ Intent.EXTRA_MIME_TYPES,
+ arrayOf("image/jpeg", "image/png", "image/webp", "image/heic")
+ )
+ pictureForDocDetectionResult.launch(Intent.createChooser(imageIntent, "Select Picture"))
+ }
+
+}
+
diff --git a/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/rtu_ui/AcknowledgeScreenSnippet.kt b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/rtu_ui/AcknowledgeScreenSnippet.kt
index 08bd4300..5c6bf379 100644
--- a/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/rtu_ui/AcknowledgeScreenSnippet.kt
+++ b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/rtu_ui/AcknowledgeScreenSnippet.kt
@@ -59,20 +59,16 @@ class AcknowledgeScreenSnippet : AppCompatActivity() {
// - `NONE`: Skips the quality check entirely.
acknowledgementMode = AcknowledgementMode.ALWAYS
- // Set the minimum acceptable document quality.
- // Options: excellent, good, reasonable, poor, veryPoor, or noDocument.
- minimumQuality = DocumentQuality.GOOD
-
// Set the background color for the acknowledgment screen.
backgroundColor = ScanbotColor(value = "#EFEFEF")
// You can also configure the buttons in the bottom bar of the acknowledgment screen.
// e.g To force the user to retake, if the captured document is not OK.
- bottomBar.acceptWhenNotOkButton.visible = false
+ bottomBar.acceptWhenUncertainButton.visible = false
// Hide the titles of the buttons.
- bottomBar.acceptWhenNotOkButton.title.visible = false
- bottomBar.acceptWhenOkButton.title.visible = false
+ bottomBar.acceptWhenUncertainButton.title.visible = false
+ bottomBar.acceptWhenAcceptableButton.title.visible = false
bottomBar.retakeButton.title.visible = false
// Configure the acknowledgment screen's hint message which is shown if the least acceptable quality is not met.
diff --git a/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/rtu_ui/DocumentStraighteningSnippet.kt b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/rtu_ui/DocumentStraighteningSnippet.kt
new file mode 100644
index 00000000..0e1487fc
--- /dev/null
+++ b/document-scanner-ready-to-use-ui-example/app/src/main/java/com/example/scanbot/doc_code_snippet/rtu_ui/DocumentStraighteningSnippet.kt
@@ -0,0 +1,66 @@
+package com.example.scanbot.doc_code_snippet.rtu_ui
+
+
+import android.os.Bundle
+import androidx.activity.result.ActivityResultLauncher
+import androidx.appcompat.app.AppCompatActivity
+import io.scanbot.common.Result
+import io.scanbot.common.onCancellation
+import io.scanbot.common.onFailure
+import io.scanbot.common.onSuccess
+import io.scanbot.sdk.documentscanner.DocumentStraighteningMode
+import io.scanbot.sdk.documentscanner.DocumentStraighteningParameters
+import io.scanbot.sdk.geometry.AspectRatio
+
+import io.scanbot.sdk.ui_v2.document.DocumentScannerActivity
+import io.scanbot.sdk.ui_v2.document.configuration.DocumentScanningFlow
+
+
+class DocumentStraighteningSnippet : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // In the real application, you should call this function on button click
+ startScanning()
+ }
+
+ private val context = this
+ private val documentScannerResult: ActivityResultLauncher by lazy {
+ registerForActivityResult(DocumentScannerActivity.ResultContract()) { result ->
+ result.onSuccess { document ->
+ // Handle the scanned document.
+ }.onCancellation {
+ // Indicates that the cancel button was tapped. Or screen is closed by other reason.
+ }.onFailure {
+ when (it) {
+ is Result.InvalidLicenseError -> {
+ // indicate that the Scanbot SDK license is invalid
+ }
+
+ else -> {
+ // Handle other errors
+ }
+ }
+ }
+ }
+ }
+
+ // @Tag("Set Document Straightening Parameters")
+ fun startScanning() {
+ // Create the default configuration object.
+ val configuration = DocumentScanningFlow().apply {
+ // Set document straightening parameters for the scanning screen.
+ outputSettings.apply {
+ straighteningParameters = DocumentStraighteningParameters(
+ straighteningMode = DocumentStraighteningMode.STRAIGHTEN,
+ // Expected aspect ratios for the documents. Comment if unknown.
+ aspectRatios = listOf(AspectRatio(3.0, 4.0))
+ )
+ }
+ }
+ // Start the recognizer activity.
+ documentScannerResult.launch(configuration)
+ }
+ // @EndTag("Set Document Straightening Parameters")
+
+}
+