[英]Squeezing/Squashing of Images in iOS Swift
有几种方法可以做到这一点......
如果我们将其用作原始图像:
它有一个透明的边界框......所以它在图像编辑程序中看起来像这样:
如果您只处理它在运行时的外观,您可以使用UIImageView
和Content Mode: Scale to Fill
然后调整图像视图的宽度。
如果您想实际扩展UIImage
,这个简单的扩展将完成这项工作:
extension UIImage {
func squeeze(w: CGFloat, h: CGFloat) -> UIImage {
let newWidth: CGFloat = self.width * w
let newHeight: CGFloat = self.height * h
let sz: CGSize = CGSize(width: newWidth, height: newHeight)
let renderer: UIGraphicsImageRenderer = UIGraphicsImageRenderer(size: sz)
let img = renderer.image { _ in
self.draw(in: CGRect(origin: .zero, size: sz))
}
return img
}
}
(图像视图有一个绿色边框,所以我们可以看到框架)。
这是您可以使用的一些示例代码:
class ViewController: UIViewController, UITextFieldDelegate {
var origIMG: UIImage!
let imgViewA = UIImageView()
let imgViewB = UIImageView()
let imgViewC = UIImageView()
let st = UIStackView()
let statusLabel = UILabel()
let slider = UISlider()
var bWidth: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
guard let img = UIImage(named: "car1"),
let bkgImg = UIImage(named: "carsBKG")
else { return }
print(img.size)
origIMG = img
// add a background image view
let vBKG = UIImageView(image: bkgImg)
st.axis = .vertical
st.alignment = .center
st.spacing = 2
[imgViewA, imgViewB, imgViewC].forEach { v in
v.layer.borderWidth = 2
v.layer.borderColor = UIColor.green.cgColor
v.backgroundColor = .clear
v.image = origIMG
}
// for A and B, we let the image view frame scale the image
imgViewA.contentMode = .scaleToFill
imgViewB.contentMode = .scaleToFill
// for C we keep the image aspect ratio, because
// we're going to modify the UIImage size
imgViewC.contentMode = .scaleAspectFit
var label: UILabel!
label = UILabel()
label.text = "Original"
st.addArrangedSubview(label)
st.addArrangedSubview(imgViewA)
st.setCustomSpacing(20.0, after: imgViewA)
label = UILabel()
label.text = "Modify Image View Frame"
st.addArrangedSubview(label)
st.addArrangedSubview(imgViewB)
st.setCustomSpacing(20.0, after: imgViewB)
label = UILabel()
label.text = "Modify UIImage"
st.addArrangedSubview(label)
st.addArrangedSubview(imgViewC)
st.setCustomSpacing(20.0, after: imgViewC)
statusLabel.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
statusLabel.textAlignment = .center
st.addArrangedSubview(statusLabel)
slider.backgroundColor = .white.withAlphaComponent(0.6)
slider.addTarget(self, action: #selector(sliderChanged(_:)), for: .valueChanged)
st.addArrangedSubview(slider)
st.setCustomSpacing(20.0, after: slider)
vBKG.translatesAutoresizingMaskIntoConstraints = false
st.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(vBKG)
view.addSubview(st)
// we're going to modify the 2nd image view width
bWidth = imgViewB.widthAnchor.constraint(equalTo: st.widthAnchor)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
st.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
st.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
st.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
// background image view same size/position as stack view
// plus 20-points on each side
vBKG.topAnchor.constraint(equalTo: st.topAnchor, constant: -20.0),
vBKG.leadingAnchor.constraint(equalTo: st.leadingAnchor, constant: -20.0),
vBKG.trailingAnchor.constraint(equalTo: st.trailingAnchor, constant: 20.0),
vBKG.bottomAnchor.constraint(equalTo: st.bottomAnchor, constant: 20.0),
// top image (original) full width, proportional height
imgViewA.widthAnchor.constraint(equalTo: st.widthAnchor),
imgViewA.heightAnchor.constraint(equalTo: imgViewA.widthAnchor, multiplier: origIMG.height / origIMG.width),
// 2nd image starts at full width, proportional height
// we'll change the image VIEW width
bWidth,
imgViewB.heightAnchor.constraint(equalTo: imgViewA.widthAnchor, multiplier: origIMG.height / origIMG.width),
// 3rd image full width, proportional height
// we'll change the actual IMAGE
imgViewC.widthAnchor.constraint(equalTo: st.widthAnchor),
imgViewC.heightAnchor.constraint(equalTo: imgViewA.widthAnchor, multiplier: origIMG.height / origIMG.width),
slider.widthAnchor.constraint(equalTo: st.widthAnchor),
])
// start slider at 100%
slider.value = 1.0
statusLabel.text = "100%"
// let's make the labels readable
st.arrangedSubviews.forEach { vSub in
if let v = vSub as? UILabel {
v.textColor = .white
v.backgroundColor = .black.withAlphaComponent(0.4)
v.textAlignment = .center
v.widthAnchor.constraint(equalTo: st.widthAnchor).isActive = true
}
}
}
@objc func sliderChanged(_ sender: UISlider) {
let pct = CGFloat(sender.value)
// let's use a minimum scale of 0.5%
if pct < 0.05 { return }
// update imgViewB's width anchor as a percentage
bWidth.isActive = false
bWidth = imgViewB.widthAnchor.constraint(equalTo: st.widthAnchor, multiplier: pct)
bWidth.isActive = true
// set imgViewC's image to a NEW rendered UIImage
// we're scaling the width, keeping the original height
imgViewC.image = origIMG.squeeze(w: pct, h: 1.0)
statusLabel.text = "\(Int(pct * 100))%"
}
}
extension UIImage {
func squeeze(w: CGFloat, h: CGFloat) -> UIImage {
let newWidth: CGFloat = self.width * w
let newHeight: CGFloat = self.height * h
let sz: CGSize = CGSize(width: newWidth, height: newHeight)
let renderer: UIGraphicsImageRenderer = UIGraphicsImageRenderer(size: sz)
let img = renderer.image { _ in
self.draw(in: CGRect(origin: .zero, size: sz))
}
return img
}
}
运行时,它看起来像这样 - 拖动 slider 将宽度设置为原始的百分比:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.