Разработка мобильного приложения для фотопечати
Приложение для фотопечати — один из немногих мобильных продуктов, где физическое и цифровое пересекаются напрямую: пользователь выбирает фото на смартфоне, а через 2–5 дней держит в руках готовый отпечаток. Технически это означает работу с полноразмерными файлами (HEIC, RAW-конвертация, цветопроба), сложным UI редактора и интеграцией с типографским API.
Работа с изображениями: HEIC и цветопроба
iPhone по умолчанию снимает в HEIC (High Efficiency Image Container). Большинство типографий принимают только JPEG. Конвертация — на устройстве или на сервере:
import Photos
import ImageIO
func convertHEICtoJPEG(asset: PHAsset, completion: @escaping (Data?) -> Void) {
let options = PHImageRequestOptions()
options.deliveryMode = .highQualityFormat
options.isNetworkAccessAllowed = true
options.isSynchronous = false
PHImageManager.default().requestImage(
for: asset,
targetSize: PHImageManagerMaximumSize,
contentMode: .aspectFit,
options: options
) { image, info in
guard let cgImage = image?.cgImage else {
completion(nil)
return
}
let mutableData = NSMutableData()
guard let destination = CGImageDestinationCreateWithData(
mutableData, kUTTypeJPEG as CFString, 1, nil
) else {
completion(nil)
return
}
let jpegOptions: [CFString: Any] = [
kCGImageDestinationLossyCompressionQuality: 0.95,
// Сохраняем sRGB для предсказуемой цветопробы в типографии
kCGImagePropertyColorModel: kCGImagePropertyColorModelRGB
]
CGImageDestinationAddImage(destination, cgImage, jpegOptions as CFDictionary)
CGImageDestinationFinalize(destination)
completion(mutableData as Data)
}
}
Минимальное разрешение для качественной печати 10×15 см — 1200×900 px при 300 DPI. Приложение должно предупреждать пользователя, если фото слишком маленькое:
func checkPrintQuality(image: UIImage, printSizeInches: CGSize) -> PrintQuality {
let requiredWidth = printSizeInches.width * 300
let requiredHeight = printSizeInches.height * 300
return image.size.width >= requiredWidth && image.size.height >= requiredHeight
? .good
: image.size.width >= requiredWidth * 0.7 ? .acceptable : .poor
}
Редактор: кадрирование и коррекция
Редактор — центральный экран приложения. Для базовых операций (crop, rotate, brightness, contrast) на iOS используем Core Image + CIFilter:
func applyBrightnessContrast(
to image: CIImage,
brightness: Float,
contrast: Float
) -> CIImage {
guard let filter = CIFilter(name: "CIColorControls") else { return image }
filter.setValue(image, forKey: kCIInputImageKey)
filter.setValue(brightness, forKey: kCIInputBrightnessKey)
filter.setValue(contrast, forKey: kCIInputContrastKey)
return filter.outputImage ?? image
}
На Android — Coil + android.graphics.ColorMatrix для базовых фильтров, для сложных — GPUImage library.
Кадрирование под форматы печати (10×15, 15×20, 20×30, квадрат) — обязательно поддерживать фиксированный aspect ratio с плавной анимацией crop-прямоугольника.
Загрузка файлов в типографию
Фотографии весят 3–8 МБ каждая. При заказе 30+ снимков — это 100–250 МБ. Загрузка пакетами с возможностью паузы/возобновления:
// Android: WorkManager для надёжной фоновой загрузки
class PhotoUploadWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val photoIds = inputData.getStringArray("photoIds") ?: return Result.failure()
val orderId = inputData.getString("orderId") ?: return Result.failure()
photoIds.forEachIndexed { index, photoId ->
val photo = photoRepository.getById(photoId)
val success = uploadPhoto(photo, orderId)
if (!success) return Result.retry()
setProgress(workDataOf(
"uploaded" to index + 1,
"total" to photoIds.size
))
}
return Result.success()
}
}
// Запуск с Constraints — только по Wi-Fi для больших заказов
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
Интеграция с типографией
API типографий — как правило, REST с multipart/form-data для загрузки файлов и отдельными эндпоинтами для создания заказа. Распространённые поставщики: Cewe API, Fujifilm API, частные типографии с кастомным REST.
После загрузки всех файлов и создания заказа — приложение показывает статус: «В обработке» → «Передан в печать» → «Отправлен» (с трек-номером).
Ориентиры по срокам
Базовая версия (выбор фото, кадрирование, загрузка, оплата, история заказов): 5–8 недель. Расширенный редактор (фильтры, текст, коллажи) — ещё 3–4 недели. Стоимость рассчитывается индивидуально.







