Xcode 9.x 中的核心图像和 "sig abrt" 的自定义过滤器
Custom Filter of Core Image and "sig abrt" in Xcode 9.x
我正在写代码。这是我的完整源代码。
我确认我的代码在 Xcode 8.3.3.
中成功运行
但是,我的代码在 Xcode 9.x(9.1 和 9.2)中崩溃了。
确切地说,我的代码在 "filter.setValue(inputCIImage, forKey: kCIInputImageKey)" 和 "NSException (sig abrt)"
中崩溃了
用调试器也没找到原因
result of Xcode 8.3.3
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
let inputImage = UIImage(named: "testImage.png")
override func viewDidLoad() {
super.viewDidLoad()
let inputCIImage = CIImage(image: inputImage!)
let filter = CustomFilter()
filter.setValue(inputCIImage, forKey: kCIInputImageKey)
let outputImage = filter.outputImage!
let context = CIContext()
let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent)
imageView.image = UIImage(cgImage: outputCGImage!)
}
}
class CustomFilter: CIFilter {
var inputImage: CIImage?
override public var outputImage: CIImage! {
get {
if let inputImage = self.inputImage {
let args = [inputImage as AnyObject]
return createCustomKernel().apply(extent: inputImage.extent, arguments: args)
} else {
return nil
}
}
}
func createCustomKernel() -> CIColorKernel {
let kernelString =
"kernel vec4 chromaKey(__sample s){\n" +
"vec4 newPixel = s.rgba;\n" +
"newPixel[0] = 0.0;\n" +
"newPixel[2] = newPixel[2] / 2.0;\n" +
"return newPixel;\n" + "}"
return CIColorKernel(source: kernelString)!
}
}
我能够使用 setValue(forKey:)
的唯一方法是实际 注册 我的自定义过滤器。当然,我只在 Swift 4 应用程序中这样做过,但我很惊讶这在 Swift 3.
中起作用
请记住,虽然 `setValue(forKey:) 在句法上是有效的 - 意味着它会构建 - 当 CoreImage 尝试执行你的过滤器时会出现任何错误。
我想你有两个选择:
(1) 最简单的方法是更改输入图像的传递方式(这就是我从 Swift 2 开始就做的事情)。尝试用此替换该行:
filter.inputImage = inputCIImage
(2) 注册您的过滤器。在您的 CustomFilter
class 中添加:
var inputImage: CIImage!
override var attributes: [String : Any] {
return [
kCIAttributeFilterDisplayName: "My custom filter",
"inputImage": [kCIAttributeIdentity: 0,
kCIAttributeClass: "CIImage",
kCIAttributeDisplayName: "Image",
kCIAttributeType: kCIAttributeTypeImage]
]
}
下一个子class CIFilterConstructor
:
class CustomFilters: NSObject, CIFilterConstructor {
static func registerFilters() {
CIFilter.registerName(
"My custom filter",
constructor: CustomFilters(),
classAttributes: [
kCIAttributeFilterCategories: [CategoryCustom]
])
}
func filter(withName name: String) -> CIFilter? {
switch name {
case "My custom filter":
return CustomFilter()
default:
return nil
}
}
}
最后,在您的应用代码中,执行以下两件事:
(A) 注册您的过滤器。我通常在 viewDidLoad
:
中这样做
CustomFilters.RegisterFilters()
(B) 实例化您的过滤器,按名称调用它:
let filter = CIFilter(name: "My custom filter")
我正在写代码。这是我的完整源代码。
我确认我的代码在 Xcode 8.3.3.
中成功运行但是,我的代码在 Xcode 9.x(9.1 和 9.2)中崩溃了。
确切地说,我的代码在 "filter.setValue(inputCIImage, forKey: kCIInputImageKey)" 和 "NSException (sig abrt)"
中崩溃了用调试器也没找到原因
result of Xcode 8.3.3
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
let inputImage = UIImage(named: "testImage.png")
override func viewDidLoad() {
super.viewDidLoad()
let inputCIImage = CIImage(image: inputImage!)
let filter = CustomFilter()
filter.setValue(inputCIImage, forKey: kCIInputImageKey)
let outputImage = filter.outputImage!
let context = CIContext()
let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent)
imageView.image = UIImage(cgImage: outputCGImage!)
}
}
class CustomFilter: CIFilter {
var inputImage: CIImage?
override public var outputImage: CIImage! {
get {
if let inputImage = self.inputImage {
let args = [inputImage as AnyObject]
return createCustomKernel().apply(extent: inputImage.extent, arguments: args)
} else {
return nil
}
}
}
func createCustomKernel() -> CIColorKernel {
let kernelString =
"kernel vec4 chromaKey(__sample s){\n" +
"vec4 newPixel = s.rgba;\n" +
"newPixel[0] = 0.0;\n" +
"newPixel[2] = newPixel[2] / 2.0;\n" +
"return newPixel;\n" + "}"
return CIColorKernel(source: kernelString)!
}
}
我能够使用 setValue(forKey:)
的唯一方法是实际 注册 我的自定义过滤器。当然,我只在 Swift 4 应用程序中这样做过,但我很惊讶这在 Swift 3.
请记住,虽然 `setValue(forKey:) 在句法上是有效的 - 意味着它会构建 - 当 CoreImage 尝试执行你的过滤器时会出现任何错误。
我想你有两个选择:
(1) 最简单的方法是更改输入图像的传递方式(这就是我从 Swift 2 开始就做的事情)。尝试用此替换该行:
filter.inputImage = inputCIImage
(2) 注册您的过滤器。在您的 CustomFilter
class 中添加:
var inputImage: CIImage!
override var attributes: [String : Any] {
return [
kCIAttributeFilterDisplayName: "My custom filter",
"inputImage": [kCIAttributeIdentity: 0,
kCIAttributeClass: "CIImage",
kCIAttributeDisplayName: "Image",
kCIAttributeType: kCIAttributeTypeImage]
]
}
下一个子class CIFilterConstructor
:
class CustomFilters: NSObject, CIFilterConstructor {
static func registerFilters() {
CIFilter.registerName(
"My custom filter",
constructor: CustomFilters(),
classAttributes: [
kCIAttributeFilterCategories: [CategoryCustom]
])
}
func filter(withName name: String) -> CIFilter? {
switch name {
case "My custom filter":
return CustomFilter()
default:
return nil
}
}
}
最后,在您的应用代码中,执行以下两件事:
(A) 注册您的过滤器。我通常在 viewDidLoad
:
CustomFilters.RegisterFilters()
(B) 实例化您的过滤器,按名称调用它:
let filter = CIFilter(name: "My custom filter")