如何在swift中在UIImage上绘制/涂鸦线?

在此处输入图像描述

我需要像上面的图片一样在UIImage中绘制/涂鸦一行,我看到很多教程在UIView上涂鸦线但在UIImage中没有。

用户在图像上涂鸦后,我想将其保存为新图像(具有线条的图像)。 我怎么在Swift中做到这一点?

我只能在UIView上找到绘制线而不是在UIImage中用于绘制UIView就像在这个youtube教程http://youtube.com/watch?v=gbFHqHHApC4中的这个,我改变它inheritanceDrawView到UIImageView

struct Stroke { let startPoint : CGPoint let endPoint : CGPoint let strokeColor : CGColor } class DrawView : UIImageView { var isDrawing = false var lastPoint : CGPoint! var strokeColor : CGColor! = UIColor.black.cgColor var strokes = [Stroke]() override func touchesBegan(_ touches: Set, with event: UIEvent?) { guard !isDrawing else { return } isDrawing = true guard let touch = touches.first else {return} let currentPoint = touch.location(in: self) lastPoint = currentPoint print(currentPoint) } override func touchesMoved(_ touches: Set, with event: UIEvent?) { guard isDrawing else { return} guard let touch = touches.first else {return} let currentPoint = touch.location(in: self) let stroke = Stroke(startPoint: lastPoint, endPoint: currentPoint, strokeColor: strokeColor) strokes.append(stroke) lastPoint = currentPoint setNeedsDisplay() print(currentPoint) } override func touchesEnded(_ touches: Set, with event: UIEvent?) { guard isDrawing else { return} isDrawing = false guard let touch = touches.first else {return} let currentPoint = touch.location(in: self) let stroke = Stroke(startPoint: lastPoint, endPoint: currentPoint, strokeColor: strokeColor) strokes.append(stroke) setNeedsDisplay() lastPoint = nil print(currentPoint) } override func draw(_ rect: CGRect) { let context = UIGraphicsGetCurrentContext() context?.setLineWidth(5) context?.setLineCap(.round) for stroke in strokes { context?.beginPath() context?.move(to: stroke.startPoint) context?.addLine(to: stroke.endPoint) context?.setStrokeColor(stroke.strokeColor) context?.strokePath() } } func erase() { strokes = [] strokeColor = UIColor.black.cgColor setNeedsDisplay() } } 

我在故事板中分配了UIImage以使用自定义类“DrawView”,就像我上面的代码一样,但我不知道为什么这些行没有出现在我的UIImage上

细节

Xcode 9.3,Swift 4.1

 // https://stackoverflow.com/a/41009006/4488252 class DrawingImageView: UIImageView { var path = UIBezierPath() var previousTouchPoint = CGPoint.zero var shapeLayer = CAShapeLayer() override func awakeFromNib() { super.awakeFromNib() setupView() } override init(frame: CGRect) { super.init(frame: frame) setupView() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func setupView(){ self.layer.addSublayer(shapeLayer) self.shapeLayer.lineWidth = 4 self.shapeLayer.strokeColor = UIColor.white.cgColor self.isUserInteractionEnabled = true } override func touchesBegan(_ touches: Set, with event: UIEvent?) { super.touchesBegan(touches, with: event) if let location = touches.first?.location(in: self){ previousTouchPoint = location } } override func touchesMoved(_ touches: Set, 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 } } } // https://stackoverflow.com/a/40953026/4488252 extension UIView { var screenShot: UIImage? { let scale = UIScreen.main.scale UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale); if let context = UIGraphicsGetCurrentContext() { layer.render(in: context) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return screenshot } return nil } } 

用法

  1. 将DrawingImageView添加到根(父)视图(触摸绘图将自动启用)
  2. 要保存UIImage,请使用drawingImageView.screenShot

完整样本

不要忘记在此处添加解决方案代码

 import UIKit class ViewController: UIViewController { fileprivate weak var savedImageView: UIImageView! fileprivate weak var drawingImageView: UIImageView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. let drawingImageView = addImageView(image: UIImage(named: "swift")) as DrawingImageView drawingImageView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true drawingImageView.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height/3).isActive = true self.drawingImageView = drawingImageView let button = UIButton() button.setTitle("Save Image", for: .normal) button.translatesAutoresizingMaskIntoConstraints = false button.setTitleColor(.blue, for: .normal) view.addSubview(button) button.topAnchor.constraint(equalTo:drawingImageView.bottomAnchor, constant: 60).isActive = true button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true button.heightAnchor.constraint(equalToConstant: 44).isActive = true button.addTarget(self, action: #selector(saveImageButtonTouchUpInside), for: .touchUpInside) let savedImageView = addImageView() savedImageView.topAnchor.constraint(equalTo: button.bottomAnchor, constant: 60).isActive = true savedImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true self.savedImageView = savedImageView } private func addImageView(image: UIImage? = nil) -> T { let imageView = T(frame: .zero) imageView.contentMode = .scaleAspectFit imageView.image = image view.addSubview(imageView) imageView.translatesAutoresizingMaskIntoConstraints = false imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true return imageView } @objc func saveImageButtonTouchUpInside(sender: UIButton) { savedImageView.image = drawingImageView.screenShot } } 

结果

在此处输入图像描述 在此处输入图像描述

您可以将UIImageView置于背景中,将UIView置于其顶部,然后将UIView捕获为Image并合并它。

请参阅此内容以捕获UIView: 如何在不损失视网膜显示质量的情况下将UIView捕获到UIImage

然后使用以下方法合并它:

 func mergeImages (forgroundImage : UIImage, backgroundImage : UIImage, size : CGSize) -> UIImage { let bottomImage = backgroundImage UIGraphicsBeginImageContext(size) let areaSize = CGRect(x: 0, y: 0, width: size.width, height: size.height) bottomImage.draw(in: areaSize) let topImage = forgroundImage topImage.draw(in: areaSize, blendMode: .normal, alpha: 1.0) let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return newImage } 

这可能对你有所帮助。 请参阅链接

如何在Swift中绘制图像?

  1. 制作图像图形上下文。 (在iOS 10之前,您可以通过调用UIGraphicsBeginImageContextWithOptions来完成此操作。在iOS 10中,还有另一种方法,UIGraphicsImageRenderer,但如果您不想使用它,则不必使用它。)

  2. 将图像绘制(即复制)到上下文中。 (对于这个目的,UIImage实际上有绘制…方法。)

  3. 在上下文中绘制线条。 (这里有CGContext函数。)

  4. 从上下文中提取结果图像。 (例如,如果您使用了UIGraphicsBeginImageContextWithOptions,则可以使用UIGraphicsGetImageFromCurrentImageContext。)然后关闭上下文。