gpt4 book ai didi

swift - 在 CALayer 上使用自定义 CIFilter 显示 CALayer 没有变化

转载 作者:行者123 更新时间:2023-12-02 18:43:40 27 4
gpt4 key购买 nike

我们正在尝试创建一个自定义的 CIFilter 以添加到我们的 CALayer 的顶部。 如何只有默认的 CIFilter 似乎可以在 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。

我们不知道需要什么才能让自定义 CIFilterCALayer 一起工作,而且似乎找不到任何相关信息。

请注意,我们不是在寻找这种类型的 CIFilter 或其他获取过滤器结果的方法。我们需要自定义 CIFilter 来处理 CALayer。

最佳答案

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

self.view.wantsLayer = true

但你也想这样做:

self.view.layerUsesCoreImageFilters = true

结果没有那一行:

enter image description here

结果 那一行:

enter image description here

(不要问我为什么“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 从未被请求?

关于swift - 在 CALayer 上使用自定义 CIFilter 显示 CALayer 没有变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67740708/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com