Feature: OCR Text Extraction
Relevant source files
The following files were used as context for generating this wiki page:- app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt
- app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt
- app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt
- app/src/main/java/com/musagenius/ocrapp/domain/model/OCRResult.kt
- app/src/main/java/com/musagenius/ocrapp/presentation/ui/ocr/OCRResultScreen.kt
- TODO.md
- README.md
- app/src/main/assets/tessdata/README.md
- app/src/main/java/com/musagenius/ocrapp/domain/model/ScanResult.kt
The OCR Text Extraction feature is the core functionality of the application, enabling users to extract text from images entirely offline. It is built upon the Tesseract OCR engine, wrapped in a modern Android architecture using Jetpack Compose for the UI, Hilt for dependency injection, and a clean MVVM pattern. The system is designed to be robust, handling image processing, asynchronous operations, and state management in a decoupled and testable manner.
The entire process, from image capture to displaying the extracted text, is managed through a reactive data flow. The feature supports multiple languages through downloadable Tesseract trained data files and includes image preprocessing steps to enhance accuracy.
Sources: README.md, ROADMAP.md, app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt
Architecture Overview
The feature follows a clean architecture pattern, separating concerns into three main layers: Presentation, Domain, and Data. This ensures a scalable and maintainable codebase.
This diagram shows the separation of layers. The UI (OCRResultScreen) interacts with the OCRViewModel, which uses a ProcessImageUseCase to access the OCRService. The OCRServiceImpl is the concrete implementation that uses the Tesseract library.
Sources: README.md, app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt:19, app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:28
Core Components
OCRServiceImpl
This singleton class is the heart of the OCR functionality. It acts as a wrapper around the native Tesseract TessBaseAPI.
- Thread Safety: It uses a
Mutex(tessMutex) to serialize all access to the Tesseract API, preventing race conditions and ensuring that only one OCR operation runs at a time. - Initialization: It handles the initialization of
TessBaseAPI, including setting the language and page segmentation mode. It also manages thetessdatapath. - Language Data: On first use for a specific language, it copies the required
.traineddatafile from the app's assets to the device storage. - Image Preprocessing: It utilizes an
ImagePreprocessorto perform operations like scaling before feeding the image to Tesseract. This is configurable viaOCRConfig. - Text Recognition: The
recognizeTextandrecognizeTextWithProgressmethods perform the actual OCR, returning anOCRResultor aFlow<Result<OCRProgress>>respectively.
Sources: app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:31, 34, 63, 119, 172
OCRViewModel
This ViewModel serves as the bridge between the UI and the backend services.
- State Management: It exposes a
StateFlow<OCRUiState>that the UI observes to reactively display the current state (e.g., processing, success, error). - Event Handling: It processes UI events via an
onEventfunction, triggering actions like starting a new OCR process, retrying, or saving the result. - Job Management: It manages the OCR coroutine
Job, ensuring that previous jobs are cancelled before starting a new one to prevent concurrent processing. It also handles job cancellation and resource cleanup inonCleared. - Orchestration: It invokes the
ProcessImageUseCasewith the correctOCRConfigand updates the UI state based on the success or failure of the result. It also interacts with theScanRepositoryto save successful scans to the database.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt:25, 33, 62, 142
OCRResultScreen
This Jetpack Compose screen is responsible for rendering the UI based on the OCRUiState from the OCRViewModel.
- State-Driven UI: It displays different composables based on the state:
OCRProcessingViewwhenisProcessingis true.OCRErrorViewwhenerroris not null.OCRResultContentwhen text has been successfully extracted.
- User Actions: It provides buttons for copying text to the clipboard, sharing the text, and saving the result to history. These actions are delegated to the
OCRViewModelor handled directly by the view (like clipboard and share intents).
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/ocr/OCRResultScreen.kt:34, 69, 77, 89
Data Flow for Text Extraction
The following sequence diagram illustrates the entire process from a user providing an image to the result being displayed and saved.
Configuration and Data Models
The OCR process is configured through the OCRConfig data class, and its output is represented by OCRResult. A successful result can be persisted as a ScanResult.
OCRConfig
This data class holds all the settings for an OCR operation.
| Property | Type | Default Value | Description |
|---|---|---|---|
language | String | "eng" | The language code for Tesseract (e.g., "eng", "fra"). |
pageSegmentationMode | PageSegMode | AUTO | The Tesseract page segmentation mode, which tells Tesseract how to interpret the page layout. |
engineMode | EngineMode | DEFAULT | The OCR engine mode to use (e.g., legacy Tesseract, LSTM, or both). |
preprocessImage | Boolean | true | If true, the image will be preprocessed (e.g., scaled) before OCR. |
maxImageDimension | Int | 2000 | The maximum width or height in pixels for the image after scaling. |
enableAutoRotation | Boolean | false | If true, attempts to auto-rotate the image based on orientation detection. |
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt:6-13
OCRResult
This data class encapsulates the direct output from the Tesseract engine.
| Property | Type | Description |
|---|---|---|
text | String | The extracted text. |
confidence | Float | The mean confidence of the recognition (0.0 to 1.0). |
processingTimeMs | Long | The total time taken for the OCR process in milliseconds. |
language | String | The language used for the OCR. |
wordCount | Int | The number of words in the extracted text. |
characterCount | Int | The number of characters in the extracted text. |
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/OCRResult.kt:6-12
ScanResult
When an OCR result is saved to the history, it is converted into a ScanResult domain model, which contains additional metadata for persistence.
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/ScanResult.kt, app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt:156-169
This diagram shows the relationship between the configuration, the immediate result, and the persisted scan model.
Language Data Management
The OCR service relies on Tesseract's .traineddata files for language support.
- Storage: Language files are expected to be placed in the
app/src/main/assets/tessdata/directory during development. - Deployment: When the app is run, the
OCRServiceImplchecks if the required language file (e.g.,eng.traineddata) exists in the app's private storage directory (/files/tessdata/). - First-Use Copy: If the file does not exist, it is copied from the assets folder to the private storage. This is a one-time operation per language.
- Initialization: Tesseract is then initialized using the path to this file in the app's private storage.
This approach ensures that language data is available for offline use without needing to be downloaded from the internet, although the ROADMAP.md indicates that on-demand downloading is a planned future feature.
Sources: app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:63-71, 271-293, app/src/main/assets/tessdata/README.md
Summary
The OCR Text Extraction feature is a well-architected, offline-first system that leverages the power of Tesseract within a modern Android application structure. Its key strengths are the clear separation of concerns, reactive state management with Jetpack Compose and ViewModel, and robust, thread-safe handling of the native OCR engine. The use of configurable models like OCRConfig and clear data structures like OCRResult makes the system flexible and easy to extend.