代码之家  ›  专栏  ›  技术社区  ›  Chewie The Chorkie

如何在不拉伸原始图像的情况下扩展ciimage的空间(边界)?

  •  1
  • Chewie The Chorkie  · 技术社区  · 7 年前

    我在一个已经裁剪过的图像上应用了几个滤镜,我想在原始图像旁边有一个翻转的副本。这会使它的宽度增加两倍。

    问题:如何扩展边界以使两者都适合?.cropped(to:cgrect)将拉伸原始内容。存在现有内容的原因是因为我正在尽可能多地使用ApplyingFilter来保存处理过程。这也是我裁剪原始未镜像图像的原因。

    下面是我的ciimage“alphamaskblend2”,它带有一个合成过滤器,并对同一个图像应用转换,使其翻转并调整其位置。sourcecore.extent是我想要最终图像的大小。

        alphaMaskBlend2 = alphaMaskBlend2?.applyingFilter("CISourceAtopCompositing",
                                                          parameters: [kCIInputImageKey: (alphaMaskBlend2?.transformed(by: scaledImageTransform))!,
                                                                       kCIInputBackgroundImageKey: alphaMaskBlend2!]).cropped(to: sourceCore.extent)
    

    我在LLDB中玩过转换的位置。我发现当这个滤镜被裁剪时,最左边的图像会被拉伸。如果使用相同的钳制范围,然后重新将图像裁剪到相同的范围,则图像不再扭曲,但图像的边界仅为其应有宽度的一半。

    我能做到这一点的唯一方法是与背景图像(sourcecore)进行合成,该背景图像将是两个图像合并后的大小,然后合成另一个图像:

        alphaMaskBlend2 = alphaMaskBlend2?.applyingFilter("CISourceAtopCompositing",
                                                          parameters: [kCIInputImageKey: alphaMaskBlend2!,
                                                                       kCIInputBackgroundImageKey: sourceCore])
    
        alphaMaskBlend2 = alphaMaskBlend2?.applyingFilter("CISourceAtopCompositing",
                                                          parameters: [kCIInputImageKey: (alphaMaskBlend2?.cropped(to: cropRect).transformed(by: scaledImageTransform))!,
                                                                       kCIInputBackgroundImageKey: alphaMaskBlend2!])
    

    问题是,这比必要的要贵。我甚至用基准测试了它。如果我能用一个复合材料做这个,会更有意义。

    1 回复  |  直到 7 年前
        1
  •  1
  •   dfd    7 年前

    CIImage CIFilter CIKernel here

    GLKView

    • CIPerspectiveCorrection
    • CIConstantColor CICrop

        // use CIPerspectiveCorrection to "flip" on the Y axis
    
        let minX:CGFloat = 0
        let maxY:CGFloat = 0
        let maxX = originalImage?.extent.width
        let minY = originalImage?.extent.height
    
        let flipFilter = CIFilter(name: "CIPerspectiveCorrection")
        flipFilter?.setValue(CIVector(x: minX, y: maxY), forKey: "inputTopLeft")
        flipFilter?.setValue(CIVector(x: maxX!, y: maxY), forKey: "inputTopRight")
        flipFilter?.setValue(CIVector(x: minX, y: minY!), forKey: "inputBottomLeft")
        flipFilter?.setValue(CIVector(x: maxX!, y: minY!), forKey: "inputBottomRight")
        flipFilter?.setValue(originalImage, forKey: "inputImage")
        flippedImage = flipFilter?.outputImage
    

        let paletteFilter = CIFilter(name: "CIConstantColorGenerator")
        paletteFilter?.setValue(CIColor(red: 0.7, green: 0.4, blue: 0.4), forKey: "inputColor")
        paletteImage = paletteFilter?.outputImage
        let cropFilter = CIFilter(name: "CICrop")
        cropFilter?.setValue(paletteImage, forKey: "inputImage")
        cropFilter?.setValue(CIVector(x: 0, y: 0, z: (originalImage?.extent.width)! * 2, w: (originalImage?.extent.height)!), forKey: "inputRectangle")
        paletteImage = cropFilter?.outputImage
    

        // register and use stitch filer
    
        StitchedFilters.registerFilters()
        let stitchFilter = CIFilter(name: "Stitch")
        stitchFilter?.setValue(originalImage?.extent.width, forKey: "inputThreshold")
        stitchFilter?.setValue(paletteImage, forKey: "inputPalette")
        stitchFilter?.setValue(originalImage, forKey: "inputOriginal")
        stitchFilter?.setValue(flippedImage, forKey: "inputFlipped")
        finalImage = stitchFilter?.outputImage
    

    viewDidLoad

    func openKernelFile(_ name:String) -> String {
        let filePath = Bundle.main.path(forResource: name, ofType: ".cikernel")
        do {
            return try String(contentsOfFile: filePath!)
        }
        catch let error as NSError {
            return error.description
        }
    }
    
    let CategoryStitched = "Stitch"
    
    class StitchedFilters: NSObject, CIFilterConstructor {
        static func registerFilters() {
            CIFilter.registerName(
                "Stitch",
                constructor: StitchedFilters(),
                classAttributes: [
                    kCIAttributeFilterCategories: [CategoryStitched]
                ])
        }
        func filter(withName name: String) -> CIFilter? {
            switch name {
            case "Stitch":
                return Stitch()
            default:
                return nil
            }
        }
    }
    
    class Stitch:CIFilter {
    
        let kernel = CIKernel(source: openKernelFile("Stitch"))
        var inputThreshold:Float  = 0
        var inputPalette: CIImage!
        var inputOriginal: CIImage!
        var inputFlipped: CIImage!
    
        override var attributes: [String : Any] {
            return [
                kCIAttributeFilterDisplayName: "Stitch",
    
                "inputThreshold": [kCIAttributeIdentity: 0,
                                   kCIAttributeClass: "NSNumber",
                                   kCIAttributeDisplayName: "Threshold",
                                   kCIAttributeDefault: 0.5,
                                   kCIAttributeMin: 0,
                                   kCIAttributeSliderMin: 0,
                                   kCIAttributeSliderMax: 1,
                                   kCIAttributeType: kCIAttributeTypeScalar],
    
                "inputPalette": [kCIAttributeIdentity: 0,
                                 kCIAttributeClass: "CIImage",
                                 kCIAttributeDisplayName: "Palette",
                                 kCIAttributeType: kCIAttributeTypeImage],
    
                "inputOriginal": [kCIAttributeIdentity: 0,
                                  kCIAttributeClass: "CIImage",
                                  kCIAttributeDisplayName: "Original",
                                  kCIAttributeType: kCIAttributeTypeImage],
    
                "inputFlipped": [kCIAttributeIdentity: 0,
                                 kCIAttributeClass: "CIImage",
                                 kCIAttributeDisplayName: "Flipped",
                                 kCIAttributeType: kCIAttributeTypeImage]
            ]
        }
        override init() {
            super.init()
        }
        override func setValue(_ value: Any?, forKey key: String) {
            switch key {
            case "inputThreshold":
                inputThreshold = value as! Float
            case "inputPalette":
                inputPalette = value as! CIImage
            case "inputOriginal":
                inputOriginal = value as! CIImage
            case "inputFlipped":
                inputFlipped = value as! CIImage
            default:
                break
            }
        }
        @available(*, unavailable) required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        override var  outputImage: CIImage {
            return kernel!.apply(
                extent: inputPalette.extent,
                roiCallback: {(index, rect) in return rect},
                arguments: [
                    inputThreshold as Any,
                    inputPalette as Any,
                    inputOriginal as Any,
                    inputFlipped as Any
                ])!
        }
    }
    

    kernel vec4 stitch(float threshold, sampler palette, sampler original, sampler flipped) {
        vec2 coord = destCoord();
        if (coord.x < threshold) {
            return sample(original, samplerCoord(original));
        } else {
            vec2 flippedCoord = coord - vec2(threshold, 0.0);
            vec2 flippedCoordinate = samplerTransform(flipped, flippedCoord);
            return sample(flipped, flippedCoordinate);
        }
    }
    

    CIKernels CIFilters C