首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在CALayer上使用自定义CALayer显示对CALayer没有任何更改

在CALayer上使用自定义CALayer显示对CALayer没有任何更改
EN

Stack Overflow用户
提问于 2021-05-28 14:24:34
回答 2查看 484关注 0票数 2

我们正在尝试创建一个自定义CIFilter,以在CALayer's.之上添加--无论什么时候,默认的CIFilters似乎只在CALayer.上工作。

我们在添加的ViewController.swift上创建了一个小的新项目:

代码语言:javascript
复制
import Cocoa
import CoreImage

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Create some layers to work with! (square with gradient color)
        let mainLayer = CALayer()
        let shapeLayer = CAShapeLayer()
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [NSColor.red.cgColor, NSColor.white.cgColor, NSColor.yellow.cgColor, NSColor.black.cgColor]
        
        shapeLayer.path = CGPath(rect: CGRect(x: 0, y: 0, width: 500, height: 500), transform: nil)
        shapeLayer.fillColor = CGColor.black
        
        gradientLayer.frame = CGRect(x: 0, y: 0, width: 500, height: 500)
        gradientLayer.mask = shapeLayer
        
        gradientLayer.setAffineTransform(CGAffineTransform(translationX: 50, y: 50))
        mainLayer.addSublayer(gradientLayer)
        
        mainLayer.filters = []
        self.view.layer?.addSublayer(mainLayer)

        // Register the custom filter
        CustomFilterRegister.register()
        
        // Test with a normal image file, WORKS!
//      if let image = NSImage(named: "test"), let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) {
//          if let filter = CIFilter(name: "CustomFilter") {
//              filter.setValue(CIImage(cgImage: cgImage), forKey: kCIInputImageKey)
//              let output = filter.outputImage
//              // WORKS! Image filtered as expected!
//          }
//      }
        
        // Does NOT work. No change in color of the layer!
        if let filter = CIFilter(name: "CustomFilter") {
            filter.name = "custom"
            mainLayer.filters?.append(filter)
        }

        // This works: mainLayer and sublayers are blurred!
//      if let filter = CIFilter(name: "CIGaussianBlur") {
//          filter.name = "blur"
//          mainLayer.filters?.append(filter)
//      }


    }
}
}

我们创建了一个简单的自定义CIFilter,以便在开始构建自定义CIFilter.之前进行第一次尝试。

代码语言:javascript
复制
class CustomFilter: CIFilter {
    
    // Error in xcode if you don't add this in!
    override class var supportsSecureCoding: Bool {
        return true
    }
        
    @objc dynamic var inputImage: CIImage?
    @objc dynamic var inputSaturation: CGFloat = 1
    @objc dynamic var inputBrightness: CGFloat = 0
    @objc dynamic var inputContrast: CGFloat = 1
    override func setDefaults() {
        inputSaturation = 1
        inputBrightness = 0
        inputContrast = 2
    }
    
    override public var outputImage: CIImage? {
        guard let image = inputImage else {
            return nil
        }
        return image.applyingFilter("CIPhotoEffectProcess")
            .applyingFilter("CIColorControls", parameters: [
                kCIInputSaturationKey: inputSaturation,
                kCIInputBrightnessKey: inputBrightness,
                kCIInputContrastKey: inputContrast
            ])
    }
}

class CustomFilterRegister: CIFilterConstructor {
    static func register() {
        CIFilter.registerName(
            "CustomFilter", constructor: CustomFilterRegister(),
            classAttributes: [
                kCIAttributeFilterCategories: [kCICategoryBlur, kCICategoryVideo, kCICategoryStillImage]
            ])
    }
    func filter(withName name: String) -> CIFilter? {
        switch name {
        case "CustomFilter":
            return CustomFilter()
        default:
            return nil
        }
    }
}

在ViewController中,我们添加了代码来使用正常的图像进行测试。这是工作的,所以过滤器似乎是正常的。我们还尝试了一个默认的CIGaussianBlur,它可以在CALayer.上工作。

我们不知道需要什么才能让自定义CIFilter使用CALayer,,而且似乎找不到任何关于它的信息。

请注意,我们不是寻找这种类型的CIFilter或不同的方式获得过滤器的结果。我们需要一个定制的CIFilter来处理CALayer.

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-06-24 18:24:10

正如@DonMag所指出的,它应该与他所描述的变化一起工作。不幸的是,我们今天收到了苹果的回音;

此时,有一个bug阻止自定义CIFilters在CALayer上工作。目前还没有解决这个问题的方法。

当我们提交错误时,我会在这里为感兴趣的人添加链接。但此时您不能将自定义CIFilter添加到macOS 11上的CALayer中。

希望他们能帮你们解决这个问题。

编辑

所以坏消息..。目前在macOS 12.2.1上,仍然存在相同的问题,基于我们的票证,没有发生任何事情。似乎苹果不想解决这个问题。对于那些正在寻找:这仍然不工作的CALayer,即使所有的选项,如在其他答案中描述的。内置的CIFilter按预期工作。

注意,对于使用CIFilter的导出,在CALayer上使用相同的自定义AVVideoCompositionCoreAnimationTool确实有效!

票数 2
EN

Stack Overflow用户

发布于 2021-06-08 16:26:53

我假设您在代码中未显示的地方完成了此操作:

代码语言:javascript
复制
self.view.wantsLayer = true

但你也会想要这样做:

代码语言:javascript
复制
self.view.layerUsesCoreImageFilters = true

结果不带--该行:

结果一行:

(别问我为什么"CIGaussianBlur“起作用.)

编辑--我用来生成上述输出的确切代码:

代码语言:javascript
复制
import CoreImage

class ViewController: NSViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.view.wantsLayer = true
        self.view.layerUsesCoreImageFilters = true
        
        // Create some layers to work with! (square with gradient color)
        let mainLayer = CALayer()
        let shapeLayer = CAShapeLayer()
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [NSColor.red.cgColor, NSColor.white.cgColor, NSColor.yellow.cgColor, NSColor.black.cgColor]
        
        shapeLayer.path = CGPath(rect: CGRect(x: 0, y: 0, width: 500, height: 500), transform: nil)
        shapeLayer.fillColor = CGColor.black
        
        gradientLayer.frame = CGRect(x: 0, y: 0, width: 500, height: 500)
        gradientLayer.mask = shapeLayer
        
        gradientLayer.setAffineTransform(CGAffineTransform(translationX: 50, y: 50))
        mainLayer.addSublayer(gradientLayer)
        
        mainLayer.filters = []
        self.view.layer?.addSublayer(mainLayer)

        // Register the custom filter
        CustomFilterRegister.register()
        
        let t = 2
        
        if t == 1 {
            // Test with a normal image file, WORKS!
            if let image = NSImage(named: "test"), let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) {
                if let filter = CIFilter(name: "CustomFilter") {
                    filter.setValue(CIImage(cgImage: cgImage), forKey: kCIInputImageKey)
                    let output = filter.outputImage
                    // WORKS! Image filtered as expected!
                    print()
                }
            }
        }
        
        else if t == 2 {
            // 
            // Does NOT work. No change in color of the layer!
            // 
            // This NOW works for me
            // 
            if let filter = CIFilter(name: "CustomFilter") {
                filter.name = "custom"
                mainLayer.filters?.append(filter)
            }
            
        } else {
            
            // This works: mainLayer and sublayers are blurred!
            if let filter = CIFilter(name: "CIGaussianBlur") {
                filter.name = "blur"
                mainLayer.filters?.append(filter)
            }
            
        }
        
    }
}

class CustomFilter: CIFilter {
    
    // Error in xcode if you don't add this in!
    override class var supportsSecureCoding: Bool {
        return true
    }
    
    @objc dynamic var inputImage: CIImage?
    @objc dynamic var inputSaturation: CGFloat = 1
    @objc dynamic var inputBrightness: CGFloat = 0
    @objc dynamic var inputContrast: CGFloat = 1
    override func setDefaults() {
        inputSaturation = 1
        inputBrightness = 0
        inputContrast = 2
    }
    
    override public var outputImage: CIImage? {
        guard let image = inputImage else {
            return nil
        }
        return image.applyingFilter("CIPhotoEffectProcess")
            .applyingFilter("CIColorControls", parameters: [
                kCIInputSaturationKey: inputSaturation,
                kCIInputBrightnessKey: inputBrightness,
                kCIInputContrastKey: inputContrast
            ])
    }
}

class CustomFilterRegister: CIFilterConstructor {
    static func register() {
        CIFilter.registerName(
            "CustomFilter", constructor: CustomFilterRegister(),
            classAttributes: [
                kCIAttributeFilterCategories: [kCICategoryBlur, kCICategoryVideo, kCICategoryStillImage]
            ])
    }
    func filter(withName name: String) -> CIFilter? {
        switch name {
        case "CustomFilter":
            return CustomFilter()
        default:
            return nil
        }
    }
}

编辑

奇怪的是,如果我添加一个计数器var和print()语句,如下所示:

代码语言:javascript
复制
var applyCount: Int = 0

override public var outputImage: CIImage? {
    print("getting outputImage...")
    guard let image = inputImage else {
        return nil
    }
    applyCount += 1
    print("apply", applyCount)
    return image.applyingFilter("CIPhotoEffectProcess")
        .applyingFilter("CIColorControls", parameters: [
            kCIInputSaturationKey: inputSaturation,
            kCIInputBrightnessKey: inputBrightness,
            kCIInputContrastKey: inputContrast
        ])
}

在macOS 10.15.4 / Xcode 12.4中,我在调试控制台中得到了这样的信息:

代码语言:javascript
复制
getting outputImage...
apply 1
getting outputImage...
apply 2
getting outputImage...
apply 3
getting outputImage...
apply 4
getting outputImage...
apply 5
getting outputImage...
apply 6
getting outputImage...
apply 7
getting outputImage...
apply 8
getting outputImage...
apply 9
getting outputImage...
apply 10
getting outputImage...
apply 11
getting outputImage...
apply 12
getting outputImage...
apply 13
getting outputImage...
apply 14
getting outputImage...
apply 15
getting outputImage...
apply 16

(例如,当窗口改变大小时,它继续被反复调用)。

但是,在macOS 11.4 / Xcode 12.5.1上运行时,调试控制台中的nothing .从来没有要求过outputImage

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67740708

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档