60 lines
2.1 KiB
Swift
60 lines
2.1 KiB
Swift
//
|
|
// TravelAlbumAutoRetouchProcessor.swift
|
|
// suixinkan
|
|
//
|
|
|
|
import Foundation
|
|
import UIKit
|
|
|
|
/// 自动 AI 修图处理接口,把本地原图与已选模板转换为可持久化的结果数据。
|
|
@MainActor
|
|
protocol TravelAlbumAutoRetouchProcessing {
|
|
/// 按指定模板处理一张本地照片。
|
|
func process(sourceURL: URL, preset: TravelAlbumEditPreset) async throws -> Data
|
|
}
|
|
|
|
/// 使用项目现有 Core Image 效果生成自动修图演示结果。
|
|
@MainActor
|
|
final class TravelAlbumAutoRetouchProcessor: TravelAlbumAutoRetouchProcessing {
|
|
private let processingDelayNanoseconds: UInt64
|
|
|
|
/// 创建本地修图处理器,默认保留短暂处理时间用于展示“修图中”状态。
|
|
init(processingDelayNanoseconds: UInt64 = 900_000_000) {
|
|
self.processingDelayNanoseconds = processingDelayNanoseconds
|
|
}
|
|
|
|
func process(sourceURL: URL, preset: TravelAlbumEditPreset) async throws -> Data {
|
|
let sourceData = try Data(contentsOf: sourceURL)
|
|
guard let sourceImage = UIImage(data: sourceData) else {
|
|
throw TravelAlbumAutoRetouchError.invalidSourceImage
|
|
}
|
|
if processingDelayNanoseconds > 0 {
|
|
try await Task.sleep(nanoseconds: processingDelayNanoseconds)
|
|
}
|
|
try Task.checkCancellation()
|
|
let editedImage = TravelAlbumAIEditImageProcessor.render(effect: preset.effect, source: sourceImage)
|
|
guard let resultData = editedImage.jpegData(compressionQuality: 0.92) else {
|
|
throw TravelAlbumAutoRetouchError.resultEncodingFailed
|
|
}
|
|
return resultData
|
|
}
|
|
}
|
|
|
|
/// 本地自动 AI 修图过程的可展示错误。
|
|
enum TravelAlbumAutoRetouchError: LocalizedError, Equatable {
|
|
case invalidSourceImage
|
|
case resultEncodingFailed
|
|
case invalidImageData
|
|
|
|
var errorDescription: String? {
|
|
switch self {
|
|
case .invalidSourceImage:
|
|
return "原图无法读取,修图失败"
|
|
case .resultEncodingFailed:
|
|
return "修图结果生成失败"
|
|
case .invalidImageData:
|
|
return "修图结果无法读取"
|
|
}
|
|
}
|
|
}
|