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

时间:2018-04-19 11:22:42

标签: ios swift uiimage

enter image description here

我需要在UIImage中绘制/涂鸦一行,如上图所示,我在UIView上看到很多教程涂鸦线,但在UIImage中没有。

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

我只能在UIView上找到不在UIImage中的绘制线 UIView上的绘图就像这个youtube教程中的http://youtube.com/watch?v=gbFHqHHApC4一样,我将其更改为继承DrawView为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<UITouch>, 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<UITouch>, 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<UITouch>, 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以使用自定义类&#34; DrawView&#34;就像我上面的代码一样,但我不知道为什么这些线条没有出现在我的UIImage上

3 个答案:

答案 0 :(得分:5)

详细

  • Xcode 10.2.1(10E1001),Swift 5

解决方案

value, ok := c.urls[key]
return value, ok

用法

  1. 将DrawingImageView添加到根(父)视图(触摸绘图将自动启用)
  2. 要保存UIImage,请使用import UIKit // https://stackoverflow.com/a/41009006/4488252 class DrawnImageView: UIImageView { private lazy var path = UIBezierPath() private lazy var previousTouchPoint = CGPoint.zero private lazy var shapeLayer = CAShapeLayer() 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 setupView(){ layer.addSublayer(shapeLayer) shapeLayer.lineWidth = 4 shapeLayer.strokeColor = UIColor.white.cgColor isUserInteractionEnabled = true } 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 } } } // 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 } }
  3. 完整样本

      

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

    drawingImageView.screenShot

    结果

    enter image description here enter image description here

答案 1 :(得分:3)

您可以将UIImageView置于后台,将UIView置于其顶部,然后将UIView捕获为图像并合并。

请参阅此内容以捕获UIView:How to capture UIView to UIImage without loss of quality on retina display

然后使用以下方法合并:

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
}

答案 2 :(得分:0)

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

How do I draw on an image in Swift?

  1. 制作图像图形上下文。 (在iOS 10之前,你可以通过调用UIGraphicsBeginImageContextWithOptions来实现。在iOS 10中还有另一种方式,UIGraphicsImageRenderer,但如果你不想,你不必使用它。)

  2. 将图像绘制(即复制)到上下文中。 (UIImage实际上已经为此目的绘制了......方法。)

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

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