Fix ImagePipeline operation rendering

Update MaskOperation to store mask dimensions for reconstruction.
Implement proper operation rendering in ImagePipeline:
- Apply mask+inpaint operations with proper mask reconstruction
- Handle adjustment operations by type (brightness/contrast/saturation)
- Scale masks when rendering previews at reduced resolution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-23 23:43:53 -05:00
parent 48ee7ecd7c
commit 00138d944d
3 changed files with 88 additions and 11 deletions

View File

@@ -172,13 +172,19 @@ final class EditorViewModel {
// Add operation to project
if var project = project {
let maskData = MaskData(from: mask)?.data ?? Data()
let maskOp = MaskOperation(toolType: toolTypeForCurrentTool(), maskData: maskData)
let inpaintOp = InpaintOperation(maskOperationId: maskOp.id, featherAmount: Float(featherAmount))
if let maskDataObj = MaskData(from: mask) {
let maskOp = MaskOperation(
toolType: toolTypeForCurrentTool(),
maskData: maskDataObj.data,
maskWidth: maskDataObj.width,
maskHeight: maskDataObj.height
)
let inpaintOp = InpaintOperation(maskOperationId: maskOp.id, featherAmount: Float(featherAmount))
project.addOperation(.mask(maskOp))
project.addOperation(.inpaint(inpaintOp))
self.project = project
project.addOperation(.mask(maskOp))
project.addOperation(.inpaint(inpaintOp))
self.project = project
}
}
} catch {
errorMessage = error.localizedDescription

View File

@@ -24,12 +24,16 @@ struct MaskOperation: Codable, Identifiable {
let id: UUID
let toolType: ToolType
let maskData: Data
let maskWidth: Int
let maskHeight: Int
let timestamp: Date
init(id: UUID = UUID(), toolType: ToolType, maskData: Data, timestamp: Date = Date()) {
init(id: UUID = UUID(), toolType: ToolType, maskData: Data, maskWidth: Int, maskHeight: Int, timestamp: Date = Date()) {
self.id = id
self.toolType = toolType
self.maskData = maskData
self.maskWidth = maskWidth
self.maskHeight = maskHeight
self.timestamp = timestamp
}
}

View File

@@ -13,6 +13,7 @@ import UIKit
actor ImagePipeline {
private let context: CIContext
private let inpaintEngine = InpaintEngine()
init() {
self.context = CIContext(options: [
@@ -29,12 +30,17 @@ actor ImagePipeline {
// Scale down for preview if needed
var image = originalImage
let scaleFactor: CGFloat
if image.width > maxSize || image.height > maxSize {
let scale = CGFloat(maxSize) / CGFloat(max(image.width, image.height))
image = try scaleImage(image, scale: scale)
scaleFactor = CGFloat(maxSize) / CGFloat(max(image.width, image.height))
image = try scaleImage(image, scale: scaleFactor)
} else {
scaleFactor = 1.0
}
// Apply operations (placeholder for now)
// Apply operations
image = try await applyOperations(operations, to: image, scaleFactor: scaleFactor)
return image
}
@@ -43,7 +49,68 @@ actor ImagePipeline {
operations: [EditOperation]
) async throws -> CGImage {
// Apply operations at full resolution
return originalImage
var image = originalImage
image = try await applyOperations(operations, to: image, scaleFactor: 1.0)
return image
}
private func applyOperations(
_ operations: [EditOperation],
to image: CGImage,
scaleFactor: CGFloat
) async throws -> CGImage {
var currentImage = image
// Group mask and inpaint operations
var pendingMask: MaskOperation?
for operation in operations {
switch operation {
case .mask(let maskOp):
pendingMask = maskOp
case .inpaint:
if let maskOp = pendingMask {
let maskData = MaskData(
width: maskOp.maskWidth,
height: maskOp.maskHeight,
data: maskOp.maskData
)
if let mask = maskData.toCGImage() {
// Scale mask if needed
let scaledMask: CGImage
if scaleFactor != 1.0 {
scaledMask = try scaleImage(mask, scale: scaleFactor)
} else {
scaledMask = mask
}
// Apply inpainting
currentImage = try await inpaintEngine.inpaint(
image: currentImage,
mask: scaledMask
)
}
}
pendingMask = nil
case .adjustment(let adjustment):
currentImage = applyAdjustment(adjustment, to: currentImage) ?? currentImage
}
}
return currentImage
}
private func applyAdjustment(_ adjustment: AdjustmentOperation, to image: CGImage) -> CGImage? {
switch adjustment.type {
case .brightness:
return applyColorAdjustment(to: image, brightness: adjustment.value)
case .contrast:
return applyColorAdjustment(to: image, contrast: adjustment.value)
case .saturation:
return applyColorAdjustment(to: image, saturation: adjustment.value)
}
}
func applyColorAdjustment(