我一直在使用各种 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
<小时/>结果:
关于ios - CIHeightFieldFromMask 输出图像与输入相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60193391/