Выходное изображение CIHeightFieldFromMask совпадает с входным - PullRequest
0 голосов
/ 12 февраля 2020

Я использовал различные фильтры CIF для достижения определенного эффекта, но, сужая мою проблему, я обнаружил, что CIHeightFieldFromMask не дает результата; Это означает, что изображение маски выглядит точно так же после применения фильтра. Я использую то же самое черно-белое текстовое изображение, которое используется в Apple Docs .

ciImage = ciImage
        .applyingFilter("CIHeightFieldFromMask", parameters: [kCIInputImageKey: ciImage,
                                                              kCIInputRadiusKey: ShadedHeightMaskInputRadius]) 

ShadedHeightMaskInputRadius - это значение, которое я могу изменить в диапазоне от 0 до 100 с помощью ползунка, поэтому я также попробовал все виды входных радиусов без разницы. Как я могу достичь того же точного результата, который указан в документации?

1 Ответ

0 голосов
/ 13 февраля 2020

Не знаю, почему ваша попытка не удалась ...

Это может работать для вас:

extension UIImage {
    func applyHeightMap(withRadius: Int) -> UIImage {
        guard let thisCI = CIImage(image: self) else { return self }

        let newCI = thisCI
            .applyingFilter("CIHeightFieldFromMask",
                            parameters: [kCIInputRadiusKey: withRadius])

        return UIImage(ciImage: newCI)
    }
}

Использование будет:

let newImg = self.maskImg.applyHeightMap(withRadius: self.radius)

Вот некоторые Пример кода, чтобы попробовать это. Он имеет ползунок 0 to 50 для радиуса. Это (как вы, вероятно, знаете) очень медленно на симуляторе, поэтому это обновляет изображение только при отпускании ползунка:

class CITestViewController: UIViewController {

    let theSlider: UISlider = {
        let v = UISlider()
        return v
    }()

    let theLabel: UILabel = {
        let v = UILabel()
        v.text = " "
        return v
    }()

    let theImageView: UIImageView = {
        let v = UIImageView()
        v.contentMode = .scaleAspectFit
        v.backgroundColor = .blue
        return v
    }()

    let theSpinner: UIActivityIndicatorView = {
        let v = UIActivityIndicatorView()
        return v
    }()

    var maskImg: UIImage!
    var radius: Int = 10

    override func viewDidLoad() {
        super.viewDidLoad()

        guard let mImg = UIImage(named: "ci_heightmask") else {
            fatalError("could not load ci_heightmask image")
        }

        maskImg = mImg

        [theSlider, theLabel, theImageView, theSpinner].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview($0)
        }

        let g = view.safeAreaLayoutGuide

        NSLayoutConstraint.activate([

            theSlider.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
            theSlider.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            theSlider.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),

            theLabel.topAnchor.constraint(equalTo: theSlider.bottomAnchor, constant: 20.0),
            theLabel.centerXAnchor.constraint(equalTo: theSlider.centerXAnchor, constant: 0.0),

            theImageView.topAnchor.constraint(equalTo: theLabel.bottomAnchor, constant: 20.0),
            theImageView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            theImageView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            theImageView.heightAnchor.constraint(equalTo: theImageView.widthAnchor),

            theSpinner.centerXAnchor.constraint(equalTo: theSlider.centerXAnchor),
            theSpinner.centerYAnchor.constraint(equalTo: theSlider.centerYAnchor),

        ])

        theSlider.minimumValue = 0
        theSlider.maximumValue = 1
        theSlider.value = Float(radius) / 50.0

        theSlider.addTarget(self, action: #selector(sliderChanged(_:)), for: .valueChanged)
        theSlider.addTarget(self, action: #selector(sliderReleased(_:)), for: .touchUpInside)

        theLabel.text = "Radius: \(radius)"

        updateImage()

    }

    @objc func sliderChanged(_ sender: Any) {
        if let s = sender as? UISlider {
            let v = Int((s.value * 50).rounded())
            if radius != v {
                radius = v
                theLabel.text = "Radius: \(radius)"
            }
        }
    }

    @objc func sliderReleased(_ sender: Any) {
        updateImage()
    }

    func updateImage() -> Void {

        theSlider.isHidden = true
        theSpinner.startAnimating()

        DispatchQueue.global(qos: DispatchQoS.QoSClass.userInitiated).async {

            let newImg = self.maskImg.applyHeightMap(withRadius: self.radius)

            DispatchQueue.main.async {
                self.theImageView.image = newImg
                self.theSpinner.stopAnimating()
                self.theSlider.isHidden = false
            }

        }

    }

}

ci_heightmask.png

enter image description here


Результаты:

enter image description here

enter image description here

enter image description here

...