从 UIImage 上的手绘线创建新的 UIImage - Swift

Create new UIImage from freehand drawn line over UIImage - Swift

这是我的第一个问题,所以如果我有任何不清楚的地方,请原谅。

我希望能够根据现有 UIImage1 上手绘形状的内容创建一个新的 UIImage2,以显示在现有 UIImage1 上。

视觉示例:UIImage1 是一张城市天际线照片。用户应该能够在摩天大楼周围绘制轮廓并创建一个新的 UIImage2,它将堆叠在 UIImage1 上显示,并能够编辑 UIImage 2(大小、颜色等)。

在 UIImage 上画线并不太难,但我还没有弄清楚如何在徒手绘制的形状中捕获 UIImage 的内容,从而创建一个单独的 UIImage。

非常感谢任何帮助。

如果要从屏蔽路径创建图像,您可以:

  • 根据用户手势创建 UIBezierPath
  • 将该贝塞尔曲线路径用作图像视图上的 CAShapeLayer
  • 当用户手势完成后,删除那个形状层,但创建新的形状层并将其用作遮罩;和
  • 使用 UIGraphicsImageRendererdrawHierarchy 从蒙版图像视图创建图像以渲染图像中应捕获的任何内容。

例如:

class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!
    
    private var path: UIBezierPath?
    private var strokeLayer: CAShapeLayer?
    
    @IBAction func didHandlePan(_ gesture: UIPanGestureRecognizer) {
        let location = gesture.location(in: imageView)
        
        switch gesture.state {
        case .began:
            path = UIBezierPath()
            path?.move(to: location)
            strokeLayer = CAShapeLayer()
            imageView.layer.addSublayer(strokeLayer!)
            strokeLayer?.strokeColor = #colorLiteral(red: 1, green: 0.1491314173, blue: 0, alpha: 1).cgColor
            strokeLayer?.fillColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0).cgColor
            strokeLayer?.lineWidth = 5
            strokeLayer?.path = path?.cgPath
            
        case .changed:
            path?.addLine(to: location)
            strokeLayer?.path = path?.cgPath
            
        case .cancelled, .ended:
            // remove stroke from image view
            
            strokeLayer?.removeFromSuperlayer()
            strokeLayer = nil

            // mask the image view
            
            let mask = CAShapeLayer()
            mask.fillColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1).cgColor
            mask.strokeColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0).cgColor
            mask.lineWidth = 0
            mask.path = path?.cgPath
            imageView.layer.mask = mask

            // get cropped image

            let image = imageView?.snapshot
            imageView.layer.mask = nil

            // perhaps use that image?

            imageView.image = image

        default: break
        }
    }        
}

顺便说一句,要从视图(屏蔽或其他方式)创建 UIImage,您可以使用:

extension UIView {
    var snapshot: UIImage {
        UIGraphicsImageRenderer(bounds: bounds).image { _ in
            drawHierarchy(in: bounds, afterScreenUpdates: true)
        }
    }
}

这会产生如下内容: