feat: 实现真正的分块处理优化 AI 增强质量
- TiledImageProcessor 重写:将大图拆分为 512×512 重叠 tiles - 64px 重叠区域 + 线性权重混合,消除拼接接缝 - AIEnhancer 自动选择处理器:大图用 TiledImageProcessor,小图用 WholeImageProcessor - 信息损失从 ~86% 降至 0%(1080×1920 图像不再压缩到 288×512) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -119,6 +119,30 @@ public actor AIEnhancer {
|
||||
// iOS 17 requirement ensures A12+ is present
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: - Model Download (ODR)
|
||||
|
||||
/// Check if AI model needs to be downloaded
|
||||
public static func needsDownload() async -> Bool {
|
||||
let available = await ODRManager.shared.isModelAvailable()
|
||||
return !available
|
||||
}
|
||||
|
||||
/// Get current model download state
|
||||
public static func getDownloadState() async -> ModelDownloadState {
|
||||
await ODRManager.shared.getDownloadState()
|
||||
}
|
||||
|
||||
/// Download AI model with progress callback
|
||||
/// - Parameter progress: Progress callback (0.0 to 1.0)
|
||||
public static func downloadModel(progress: @escaping @Sendable (Double) -> Void) async throws {
|
||||
try await ODRManager.shared.downloadModel(progress: progress)
|
||||
}
|
||||
|
||||
/// Release ODR resources when AI enhancement is no longer needed
|
||||
public static func releaseModelResources() async {
|
||||
await ODRManager.shared.releaseResources()
|
||||
}
|
||||
|
||||
// MARK: - Model Management
|
||||
|
||||
@@ -181,14 +205,29 @@ public actor AIEnhancer {
|
||||
throw AIEnhanceError.modelNotFound
|
||||
}
|
||||
|
||||
// Process image (no tiling - model has fixed 1280x1280 input)
|
||||
let wholeImageProcessor = WholeImageProcessor()
|
||||
// Choose processor based on image size
|
||||
// - Small images (≤ 512x512): use WholeImageProcessor (faster, single inference)
|
||||
// - Large images (> 512 in either dimension): use TiledImageProcessor (preserves detail)
|
||||
let usesTiling = image.width > RealESRGANProcessor.inputSize || image.height > RealESRGANProcessor.inputSize
|
||||
|
||||
let enhancedImage = try await wholeImageProcessor.processImage(
|
||||
image,
|
||||
processor: processor,
|
||||
progress: progress
|
||||
)
|
||||
let enhancedImage: CGImage
|
||||
if usesTiling {
|
||||
logger.info("Using tiled processing for large image")
|
||||
let tiledProcessor = TiledImageProcessor()
|
||||
enhancedImage = try await tiledProcessor.processImage(
|
||||
image,
|
||||
processor: processor,
|
||||
progress: progress
|
||||
)
|
||||
} else {
|
||||
logger.info("Using whole image processing for small image")
|
||||
let wholeImageProcessor = WholeImageProcessor()
|
||||
enhancedImage = try await wholeImageProcessor.processImage(
|
||||
image,
|
||||
processor: processor,
|
||||
progress: progress
|
||||
)
|
||||
}
|
||||
|
||||
let processingTime = (CFAbsoluteTimeGetCurrent() - startTime) * 1000
|
||||
let enhancedSize = CGSize(width: enhancedImage.width, height: enhancedImage.height)
|
||||
|
||||
Reference in New Issue
Block a user