Пользовательский фильтр Core Image и "sig abrt" в Xcode 9.x

Я пишу код. Вот мой полный исходный код.

Я подтвердил, что мой код успешно работает в Xcode 8.3.3.

Однако мой код потерпел крах в Xcode 9.x (9.1 и 9.2).

Точно, мой код потерпел крах в "filter.setValue(inputCIImage, forKey: kCIInputImageKey)" с "NSException (sig abrt)"

Я не нашел причину, хотя я использовал отладчик.

результат 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)!
}
}

1 ответ

Решение

Единственный способ, которым я смог использовать setValue(forKey:) это на самом деле зарегистрировать мой пользовательский фильтр. Конечно, я делал это только в приложении Swift 4, но я довольно удивлен, что это сработало в Swift 3.

Имейте в виду, что `setValue(forKey:) синтаксически допустим - то есть он будет собираться - когда CoreImage попытается выполнить ваш фильтр, возникнут любые ошибки.

Я думаю, у вас есть два варианта:

(1) Легче всего изменить способ передачи входного изображения (именно так я и делал со времен Swift 2). Попробуйте заменить эту строку на это:

filter.inputImage = inputCIImage

(2) Зарегистрируйте свой фильтр. В вашем CustomFilter класс, добавьте это:

var inputImage: CIImage!

override var attributes: [String : Any] {
    return [
        kCIAttributeFilterDisplayName: "My custom filter",

        "inputImage": [kCIAttributeIdentity: 0,
                       kCIAttributeClass: "CIImage",
                       kCIAttributeDisplayName: "Image",
                       kCIAttributeType: kCIAttributeTypeImage]
    ]
}

Далее подкласс 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")
Другие вопросы по тегам