如何将这个UIGraphics图像操作转换为Core Image?

How to convert this UIGraphics image operation to Core Image?

我编写了 SplitMirror 滤镜,就像在 Apple Motion 应用程序或 Snapchat 镜头中一样,使用 UIGraphics 将其用于实时摄像头输入或视频处理,以及单个图像请求它像问题中的附加图像一样工作得很好,但对于多重过滤请求则不然。我认为它的代码必须从 UIGraphics 更改为 Core Image & CIContext 以获得更好的性能和更少的内存使用,例如 CIFilters 实际上我不知道该怎么做。 我尝试了几种方法来转换它,但我坚持左右合并,这可以通过 `CICategoryCompositeOperations 过滤器来完成,但我知道哪种适合这种情况,所以需要一些帮助来解决这个问题。

过滤代码使用UIGraphics:

//
//  SplitMirror filter.swift
//  Image Editor
// 
//  Created by Coder ACJHP on 25.02.2022.
// 
// SnapChat & Tiktok & Motion App like image filter
// Inspired from 'https://support.apple.com/tr-tr/guide/motion/motn169f94ea/mac'
// Splits an image in half vertically and reverses the left remaining half to create a reflection.

final func splitMirrorFilter(processingImage image: UIImage) -> UIImage {
    // Image size
    let imageSize = image.size

    // Left half
    let leftHalfRect = CGRect(
        origin: .zero,
        size: CGSize(
                width: imageSize.width/2,
                height: imageSize.height
                )
    )
    
    // Right half
    let rightHalfRect = CGRect(
        origin: CGPoint(
            x: imageSize.width - (imageSize.width/2).rounded(),
            y: 0
        ),
        size: CGSize(
            width: imageSize.width - (imageSize.width/2).rounded(),
            height: imageSize.height
        )
    )
    // Split image into two parts
    guard let cgRightHalf = image.cgImage?.cropping(to: rightHalfRect) else { return image }
    // Flip right side to be used as left side
    let flippedLeft = UIImage(cgImage: cgRightHalf, scale: image.scale, orientation: .upMirrored)
    let unFlippedRight = UIImage(cgImage: cgRightHalf, scale: image.scale, orientation: image.imageOrientation)
    
    UIGraphicsBeginImageContextWithOptions(imageSize, false, image.scale)
    
    flippedLeft.draw(at: leftHalfRect.origin)
    unFlippedRight.draw(at: rightHalfRect.origin)
    
    guard let splitMirroredImage = UIGraphicsGetImageFromCurrentImageContext() else { return image }
    UIGraphicsEndImageContext()
    return splitMirroredImage
}

这是它用 Core Image

尝试的结果
    // Splits an image in half vertically and reverses the left remaining half to create a reflection.
final func splitMirrorFilterCIImageVersion(processingImage image: UIImage) -> CIImage? {

    
    guard let ciImageCopy = CIImage(image: image) else { return image.ciImage }
    
    // Image size
    let imageSize = ciImageCopy.extent.size
    let imageRect = CGRect(origin: .zero, size: imageSize)

    // Left half
    let leftHalfRect = CGRect(
        origin: .zero,
        size: CGSize(
                width: imageSize.width/2,
                height: imageSize.height
                )
    )
    
    // Right half
    let rightHalfRect = CGRect(
        origin: CGPoint(
            x: imageSize.width - (imageSize.width/2).rounded(),
            y: 0
        ),
        size: CGSize(
            width: imageSize.width - (imageSize.width/2).rounded(),
            height: imageSize.height
        )
    )
    
    
    
    // Split image into two parts
    let cgRightHalf = ciImageCopy.cropped(to: rightHalfRect)
    context.draw(cgRightHalf.oriented(.upMirrored), in: leftHalfRect, from: imageRect)
    context.draw(cgRightHalf, in: rightHalfRect, from: imageRect)
    
    // I'm stuck here
    
    // Merge two images into one 
    // Here I don't know which filter can be used to merge op
    // CICategoryCompositeOperation filters may fits
}

我认为你的方向是对的。

您可以使用 let leftHalf = rightHalf.transformed(by: transformation) 对其应用变换,从右半部分创建左半部分。转换应该镜像它 并且 将它转换到正确的位置,即在右半部分旁边。

您可以使用 let result = leftHalf.composited(over: rightHalf) 将两者组合成一个图像,然后使用 CIContext.

渲染该结果

Frank Schlegel 的回答中得到正确的想法后,我重写了过滤器代码,现在运行良好。

 // Splits an image in half vertically and reverses the left remaining half to create a reflection.
final func splitMirrorFilterCIImageVersion(processingImage image: UIImage) -> CIImage? {
    
    guard let ciImageCopy = CIImage(image: image) else { return image.ciImage }
    
    // Image size
    let imageSize = ciImageCopy.extent.size
    
    // Right half
    let rightHalfRect = CGRect(
        origin: CGPoint(
            x: imageSize.width - (imageSize.width/2).rounded(),
            y: 0
        ),
        size: CGSize(
            width: imageSize.width - (imageSize.width/2).rounded(),
            height: imageSize.height
        )
    )
            
    // Split image into two parts
    let ciRightHalf = ciImageCopy.cropped(to: rightHalfRect)
    // Make transform to move right part to left
    let transform = CGAffineTransform(translationX: -rightHalfRect.size.width, y: -rightHalfRect.origin.y)
    // Create left part and apply transform then flip it
    let ciLeftHalf = ciRightHalf.transformed(by: transform).oriented(.upMirrored)
            
    // Merge two images into one
    return ciLeftHalf.composited(over: ciRightHalf)
}