我假设你在代码中没有显示的地方做了这件事:
self.view.wantsLayer = true
但你也会想这样做:
self.view.layerUsesCoreImageFilters = true
结果
没有
这条线:
结果
具有
这条线:
(不管怎样,不要问我为什么“CIGaussianBlur”有效……)
编辑
-我用来产生上述输出的确切代码:
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()
这样的陈述:
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/XXcode 12.4上,我在调试控制台中得到以下结果:
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上运行时,我得到
没有什么
在调试控制台中。。。
outputImage
从未被请求?