ios - CIHeightFieldFromMask 输出图像与输入相同

标签 ios swift cifilter

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

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

ShadedHeightMaskInputRadius 是一个我可以使用 slider 在 0 到 100 之间更改的值,因此我也尝试了各种输入半径,没有任何区别。我怎样才能获得与文档中显示的相同的精确结果?

最佳答案

不确定为什么您的尝试失败...

这可能对你有用:

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 到 50 范围的半径 slider 。 (您可能知道)这在模拟器上非常慢,因此仅当您释放 slider 时才会更新图像:

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

关于ios - CIHeightFieldFromMask 输出图像与输入相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60193391/

相关文章:

android - 如何保护应用程序内的内容?

ios - 如何在 ios 13 中显示的 View Controller 下方设置系统背景颜色

swift - CIDepthBlurEffect : setting inputFocusRect

ios - Xcode 9 (9A235) iPhone X 消失了,奇怪的模拟器 : iPhone2017-A, -B -C?

ios - 在 Swift 1.2 中动态设置 tableViewCell 和 TextView 大小

ios - 将索引行传递给另一个 View

ios - 基于 json 的搜索栏过滤器

ios - 模糊 UIImage 不剪裁(Swift)

ios - CIFilter 输出图像 nil

ios - 有什么方法可以强制 UILocalNotification 默认为警报?