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:
empty
2026-01-03 21:04:22 +08:00
parent 3d1677bdb1
commit 3f503c1050
3 changed files with 464 additions and 66 deletions

View File

@@ -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)