```kotlin // filename: AndroidCropPipelinePlan.md // Architectural plan for building an Android handwriting text block cropper MVP using ML Kit. ``` ### Архитектура приложения Приложение нацелено на максимальную скорость и простоту: оно получает кадр с камеры, определяет границы бланка рецепта, выравнивает его, находит области с рукописным текстом и отправляет нарезку на бланке в виде массива `Base64` на бэкенд. --- ### Библиотеки и стек (Android / Kotlin) * **UI Framework:** Jetpack Compose + Material 3. * **Camera:** `androidx.camera:camera-camera2` (CameraX). * **Document Scanner (Выравнивание бланка):** `com.google.android.gms:play-services-mlkit-document-scanner` (Google ML Kit Document Scanner API). * **Text Detection (Поиск BoundingBoxes):** `com.google.android.gms:play-services-mlkit-text-recognition` (ML Kit Text Recognition). * **Network / HTTP:** `io.ktor:ktor-client-android` + `io.ktor:ktor-client-content-negotiation` (Ktor Client). * **Image Processing:** `io.coil-kt:coil-compose` (отображение) + стандартный `android.graphics.Bitmap`. --- ### Пошаговый план разработки для Агента #### 1. Инициализация и разрешения * Настроить `build.gradle.kts` с указанными выше библиотеками. * Запросить стандартные разрешения `CAMERA` и доступ к хранилищу. #### 2. Захват и выравнивание бланка (Document Scanner) * Использовать `GmsDocumentScannerOptions`: * Режим: `SCANNER_MODE_FULL`. * Формат: `RESULT_FORMAT_JPEG`. * Лимит страниц: `1`. * Запустить интентом `GmsDocumentScanning.getClient(options).getStartScanIntent(...)`. * Получить обратно отсканированный, обрезанный и выровненный `Uri` рецепта. #### 3. Поиск рукописных прямоугольников (Bounding Boxes) * Преобразовать `Uri` выровненного бланка в `InputImage.fromFilePath`. * Запустить `TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS)`. * Из полученного `Text` пройтись по `Text.TextBlock` или `Text.Line`. * Извлечь прямоугольники: `val rect: Rect? = block.boundingBox`. #### 4. Нарезка Bitmap (Cropping) * Загрузить исходный `Bitmap` бланка. * Для каждого полученного `Rect` выполнить: ```kotlin val cropBitmap = Bitmap.createBitmap( originalBitmap, rect.left, rect.top, rect.width(), rect.height() ) ``` * Конвертировать каждый `cropBitmap` в строку Base64 (JPEG, quality 90). #### 5. Отправка на бэкенд * Сформировать DTO: ```kotlin @Serializable data class RecipePayload( val clientVersion: String = "1.0", val snippets: List // Array of Base64 strings ) ``` * Отправить `POST`-запрос через Ktor на эндпоинт `/api/v1/recognize`.