我们正在尝试创建一个自定义CIFilter,以在CALayer's.之上添加--无论什么时候,默认的CIFilters似乎只在CALayer.上工作。
我们在添加的ViewController.swift上创建了一个小的新项目:
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.之前进行第一次尝试。
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.
发布于 2021-06-24 18:24:10
正如@DonMag所指出的,它应该与他所描述的变化一起工作。不幸的是,我们今天收到了苹果的回音;
此时,有一个bug阻止自定义CIFilters在CALayer上工作。目前还没有解决这个问题的方法。
当我们提交错误时,我会在这里为感兴趣的人添加链接。但此时您不能将自定义CIFilter添加到macOS 11上的CALayer中。
希望他们能帮你们解决这个问题。
编辑
所以坏消息..。目前在macOS 12.2.1上,仍然存在相同的问题,基于我们的票证,没有发生任何事情。似乎苹果不想解决这个问题。对于那些正在寻找:这仍然不工作的CALayer,即使所有的选项,如在其他答案中描述的。内置的CIFilter按预期工作。
注意,对于使用CIFilter的导出,在CALayer上使用相同的自定义AVVideoCompositionCoreAnimationTool确实有效!
发布于 2021-06-08 16:26:53
我假设您在代码中未显示的地方完成了此操作:
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 / Xcode 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上运行时,调试控制台中的nothing .从来没有要求过outputImage?
https://stackoverflow.com/questions/67740708
复制相似问题