UI: Image Editor Screen
Relevant source files
The following files were used as context for generating this wiki page:
- app/src/main/java/com/musagenius/ocrapp/presentation/ui/editor/ImageEditorScreen.kt
- app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/ImageEditorViewModel.kt
- app/src/main/java/com/musagenius/ocrapp/data/utils/ImageEditor.kt
- app/src/main/java/com/musagenius/ocrapp/MainActivity.kt
- app/src/main/java/com/musagenius/ocrapp/presentation/ui/ocr/OCRResultScreen.kt
The Image Editor screen provides a pre-processing step for images before they are sent to the OCR engine. Its primary function is to allow the user to rotate an image to the correct orientation, which is crucial for achieving high OCR accuracy. This feature is specifically integrated into the workflow for images selected from the device's gallery.
The screen is built using Jetpack Compose and follows an MVVM (Model-View-ViewModel) architecture. It allows for 90-degree clockwise and counter-clockwise rotations, resetting the rotation, and saving the edited image. Upon saving, the modified image is passed to the OCR Result Screen for text extraction.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/editor/ImageEditorScreen.kt:20-26, app/src/main/java/com/musagenius/ocrapp/MainActivity.kt:70-73
Navigation Flow
The ImageEditorScreen is invoked when a user selects an image from the gallery on the CameraScreen. After the user edits and saves the image, the application navigates to the OCRResultScreen, passing the URI of the newly saved, rotated image. If the user cancels, they are returned to the previous screen.
Sources: app/src/main/java/com/musagenius/ocrapp/MainActivity.kt:66-91
The diagram below illustrates the navigation path involving the Image Editor.
Architecture
The feature is implemented using a standard MVVM pattern, separating UI logic, state management, and data manipulation.
- View (
ImageEditorScreen.kt): A Jetpack Compose composable function responsible for rendering the UI based on state from the ViewModel and forwarding user events. - ViewModel (
ImageEditorViewModel.kt): A Hilt-injected ViewModel that holds the UI state (ImageEditorUiState), handles user events (ImageEditorEvent), and orchestrates the image editing process by calling theImageEditorutility. - Service/Utility (
ImageEditor.kt): A utility class responsible for the low-level image manipulation logic, such as rotating and saving bitmaps.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/editor/ImageEditorScreen.kt, app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/ImageEditorViewModel.kt, app/src/main/java/com/musagenius/ocrapp/data/utils/ImageEditor.kt
The following class diagram shows the relationship between these key components.
State and Event Management
The UI is driven by the ImageEditorUiState data class and user interactions are handled via the ImageEditorEvent sealed interface.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/ImageEditorViewModel.kt:39-45, app/src/main/java/com/musagenius/ocrapp/presentation/ui/editor/ImageEditorEvent.kt
UI State (ImageEditorUiState)
This data class represents the complete state of the editor screen at any given time.
| Property | Type | Description |
|---|---|---|
sourceImageUri | Uri? | The URI of the original image being edited. |
rotationDegrees | Float | The current rotation angle of the image in degrees. |
isProcessing | Boolean | true when the image is being saved, used to show a loading indicator. |
error | String? | An error message to be displayed to the user, or null if no error. |
User Events (ImageEditorEvent)
User actions on the screen are mapped to events, which are processed by the ImageEditorViewModel.
The flow of an event from user interaction to state update is shown below.
Core Functionality
Image Rotation
The core feature is image rotation. The ImageEditorViewModel maintains the rotationDegrees state. When the user taps the rotate buttons, the ViewModel updates this state in 90-degree increments. The actual rotation of the bitmap is only performed when the user decides to save the image.
The ImageEditor utility class contains the rotateBitmap function, which uses android.graphics.Matrix to perform the transformation.
// Source: app/src/main/java/com/musagenius/ocrapp/data/utils/ImageEditor.kt:21-38
suspend fun rotateBitmap(bitmap: Bitmap, degrees: Float): Bitmap = withContext(Dispatchers.Default) {
if (degrees == 0f) return@withContext bitmap
val matrix = Matrix().apply {
postRotate(degrees)
}
val rotated = Bitmap.createBitmap(
bitmap,
0,
0,
bitmap.width,
bitmap.height,
matrix,
true
)
// ... bitmap recycling
rotated
}
Saving the Edited Image
When the user triggers the SaveImage event, the ImageEditorViewModel initiates the save process. It calls the editImage function in the ImageEditor utility, providing the source URI and the final rotation angle. The ImageEditor then loads the bitmap, applies the rotation, saves the new bitmap to a temporary file, and returns the URI of the new file.
Note: The editImage function is designed to also handle cropping, but this functionality is not currently implemented in the ViewModel, as indicated by the cropRect = null argument.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/ImageEditorViewModel.kt:100-104, app/src/main/java/com/musagenius/ocrapp/data/utils/ImageEditor.kt:94-122
The following sequence diagram illustrates the save process.
UI Components
The UI is composed of several key Material Design 3 components.
| Component | File | Purpose |
|---|---|---|
TopAppBar | ImageEditorScreen.kt:41-76 | Contains navigation (Cancel), actions (Reset, Save), and the screen title "Edit Image". |
AsyncImage | ImageEditorScreen.kt:86-96 | Displays the image from the source URI, with its rotate modifier bound to uiState.rotationDegrees. |
CircularProgressIndicator | ImageEditorScreen.kt:102-105 | Shown as an overlay when uiState.isProcessing is true. |
FilledIconButton | ImageEditorScreen.kt:121-136, 159-174 | Used for the "Rotate Left" and "Rotate Right" buttons. |
Text | ImageEditorScreen.kt:145-151 | Displays the current rotation angle (e.g., "90°"). |
Snackbar | ImageEditorScreen.kt:179-191 | Appears at the bottom of the screen to display an error message if uiState.error is not null. |
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/editor/ImageEditorScreen.kt