如何解决在iOS中使用bezierPath移除图片背景
在所有地方搜索之后,我发现没有可用的特定来源使用bezierPath删除背景。基本上,我正在尝试实现类似的功能,例如图像抠图(您可以查看PicsArt >>图像编辑器>> CutOut)。在这种情况下,用户可以在图像上绘制任何形状,并且可以突出显示所选区域,并删除其余部分。
这就是我用来在图像上画线的地方
class DrawingImageView: UIImageView {
var path = UIBezierPath()
var prevIoUsTouchPoint = CGPoint.zero
var shapeLayer = CAShapeLayer()
var isClear: Bool = false {
didSet {
updateView()
}
}
override func awakeFromNib() {
super.awakeFromNib()
setupView()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func updateView() {
self.shapeLayer.shadowOffset = .init(width: 1,height: 1)
self.shapeLayer.shadowColor = UIColor.black.cgColor
self.shapeLayer.shadowOpacity = 1
self.shapeLayer.linewidth = 20
self.shapeLayer.lineCap = .round
self.shapeLayer.strokeColor = isClear ? UIColor.clear.cgColor : UIColor.blue.cgColor
self.shapeLayer.opacity = 0.3
self.isUserInteractionEnabled = true
}
func setupView() {
self.layer.addSublayer(shapeLayer)
updateView()
}
override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) {
super.touchesBegan(touches,with: event)
if let location = touches.first?.location(in: self){
prevIoUsTouchPoint = location
}
}
override func touchesMoved(_ touches: Set<UITouch>,with event: UIEvent?) {
super.touchesMoved(touches,with: event)
if let location = touches.first?.location(in: self){
path.move(to: location)
path.addLine(to: prevIoUsTouchPoint)
prevIoUsTouchPoint = location
shapeLayer.path = path.cgPath
}
}
}
要切出所选区域,我尝试使用cropping(to:)
的{{1}}方法。但是仅清除整个图像是行不通的。您可以在下面查看我的信息
普通图片
我不确定我是否正确执行了此操作。我也对其他方式持开放态度。
解决方法
要“删除背景”,您需要将形状图层用作遮罩。
将此功能添加到您的DrawingImageView
类中:
func applyMask() -> Void {
// set shape opacity to 1.0
shapeLayer.opacity = 1.0
// use it as a mask
layer.mask = shapeLayer
}
然后,在您的控制器中,添加一个按钮动作来调用该函数。您应该会看到所需的结果:
这是一个完整的工作示例...我还在DrawingImageView
中添加了一个bool变量和此func,以允许在“绘图”和“蒙版”模式之间进行切换,因此我可以返回并向路径添加更多
控制器
class RemoveBackgroundViewController: UIViewController {
var theDrawingView: DrawingImageView = DrawingImageView(frame: .zero)
override func viewDidLoad() {
super.viewDidLoad()
guard let img = UIImage(named: "musk") else {
fatalError("Could not load image!!!")
}
theDrawingView.image = img
let btn = UIButton()
btn.setTitle("Apply Mask",for: [])
btn.setTitleColor(.white,for: .normal)
btn.setTitleColor(.gray,for: .highlighted)
btn.backgroundColor = .red
[btn,theDrawingView].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// center the drawing image view,with 20-pts on each side
// sized proportionally to the loaded image
theDrawingView.leadingAnchor.constraint(equalTo: g.leadingAnchor,constant: 20.0),theDrawingView.trailingAnchor.constraint(equalTo: g.trailingAnchor,constant: -20.0),theDrawingView.centerYAnchor.constraint(equalTo: g.centerYAnchor),theDrawingView.heightAnchor.constraint(equalTo: theDrawingView.widthAnchor,multiplier: img.size.height / img.size.width),// constrain button above the image
btn.bottomAnchor.constraint(equalTo: theDrawingView.topAnchor,constant: -8.0),btn.centerXAnchor.constraint(equalTo: g.centerXAnchor),btn.widthAnchor.constraint(equalToConstant: 160.0),])
btn.addTarget(self,action: #selector(self.toggleActivity(_:)),for: .touchUpInside)
}
@objc func toggleActivity(_ sender: Any) {
guard let btn = sender as? UIButton else { return }
if theDrawingView.isDrawing {
theDrawingView.applyMask()
btn.setTitle("Draw More",for: [])
} else {
theDrawingView.drawMore()
btn.setTitle("Apply Mask",for: [])
}
}
}
DrawingImageView (已修改)
class DrawingImageView: UIImageView {
var path = UIBezierPath()
var previousTouchPoint = CGPoint.zero
var shapeLayer = CAShapeLayer()
var isDrawing: Bool = true
var isClear: Bool = false {
didSet {
updateView()
}
}
override func awakeFromNib() {
super.awakeFromNib()
setupView()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func updateView() {
self.shapeLayer.shadowOffset = .init(width: 1,height: 1)
self.shapeLayer.shadowColor = UIColor.black.cgColor
self.shapeLayer.shadowOpacity = 1
self.shapeLayer.lineWidth = 20
self.shapeLayer.lineCap = .round
self.shapeLayer.strokeColor = isClear ? UIColor.clear.cgColor : UIColor.blue.cgColor
self.shapeLayer.opacity = 0.3
self.isUserInteractionEnabled = true
}
func setupView() {
self.layer.addSublayer(shapeLayer)
updateView()
}
override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) {
super.touchesBegan(touches,with: event)
if !isDrawing { return }
if let location = touches.first?.location(in: self){
previousTouchPoint = location
}
}
override func touchesMoved(_ touches: Set<UITouch>,with event: UIEvent?) {
super.touchesMoved(touches,with: event)
if !isDrawing { return }
if let location = touches.first?.location(in: self){
path.move(to: location)
path.addLine(to: previousTouchPoint)
previousTouchPoint = location
shapeLayer.path = path.cgPath
}
}
func applyMask() -> Void {
// set shape opacity to 1.0
shapeLayer.opacity = 1.0
// use it as a mask
layer.mask = shapeLayer
isDrawing = false
}
func drawMore() -> Void {
// remove the mask
layer.mask = nil
// set opacity back to 0.3
shapeLayer.opacity = 0.3
// add shapeLayer back as sublayer
self.layer.addSublayer(shapeLayer)
isDrawing = true
}
}
很显然,您还有很多事情要做,但这应该可以助您一臂之力。
下一步是将图像视图框架中的路径转换/转换为原始图像尺寸,然后将蒙版应用于图像,以便将其保存下来。这对您来说应该是一个有趣的练习:)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。