【问题标题】:CIHeightFieldFromMask output image is the same as inputCIHeightFieldFromMask 输出图像与输入相同
【发布时间】:2020-02-12 16:52:35
【问题描述】:

我一直在使用各种 CIFilters 来达到一定的效果,但是当缩小我的问题时,我发现 CIHeightFieldFromMask 没有产生任何结果;这意味着我应用过滤器后蒙版图像看起来完全一样。我正在使用与the Apple Docs 中使用的完全相同的黑白文本图像。

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

ShadedHeightMaskInputRadius 是一个可以通过滑块在 0 到 100 之间变化的值,所以我也尝试了各种输入半径,没有任何区别。我怎样才能达到文档中显示的完全相同的结果?

【问题讨论】:

  • 在有问题的图片上调用.applyingFilter(),不需要设置kCIInputImageKey参数。

标签: ios swift cifilter


【解决方案1】:

不确定您的尝试失败的原因...

这可能对你有用:

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


结果:

【讨论】:

    猜你喜欢
    • 2019-08-23
    • 2021-01-25
    • 2019-03-19
    • 1970-01-01
    • 2016-06-09
    • 2021-07-21
    • 2011-04-10
    • 1970-01-01
    • 2013-05-31
    相关资源
    最近更新 更多