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:
@@ -172,14 +172,20 @@ 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)
|
||||
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
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user