3

Thanks for your time.

The image is fine before I tap the image, and then the image is compacted after I tap it.

Here is my code:

I am not using storyboard, so I create everything with code, here is the ImageView. And I added the constraints with code as well.

    let imageEditingView: UIImageView = {
    let imageView = UIImageView()
    imageView.contentMode = .scaleAspectFill
    imageView.clipsToBounds = true
    return imageView
}()

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if touches.first != nil {
        lastPoint = (touches.first?.location(in: imageEditingView))!
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    if touches.first != nil {
        let currentPoint = touches.first?.location(in: imageEditingView)
        drawLines(fromPoint: lastPoint, toPoint: currentPoint!)

        lastPoint = currentPoint!
        drawLines(fromPoint: lastPoint, toPoint: lastPoint)
    }
}

func drawLines(fromPoint: CGPoint, toPoint: CGPoint) {
    UIGraphicsBeginImageContext(imageEditingView.frame.size)
    imageEditingView.image?.draw(in: CGRect(x: 0, y: 0, width: imageEditingView.frame.width, height: imageEditingView.frame.height))

    let context = UIGraphicsGetCurrentContext()
    context?.move(to: CGPoint(x: fromPoint.x, y: fromPoint.y))
    context?.addLine(to: CGPoint(x: toPoint.x, y: toPoint.y))
    context?.setBlendMode(CGBlendMode.normal)
    context?.setLineCap(CGLineCap.round)
    context?.setLineWidth(CGFloat(Int(120 * lineWidthSliderView.value)))
    context?.setStrokeColor(red: red / 255, green: green / 255, blue: blue / 255, alpha: 0.01)
    context?.strokePath()

    imageEditingView.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}    
Bryce Chan
  • 1,639
  • 11
  • 26

1 Answers1

2

I do not know what you mean by "compacted", but I am guessing the image gets corrupted in some way because some data is lost when you convert the image to CGContext and back into an image.

I don't know how to fix this, but I would just work around this by adding a CAShapeLayer as a sublayer to the UIImageView, and drawing what you want there in the form of a CGPath. The syntax is very similar to what you are using right now, and the only effect that might not be supported is the blend mode, but you might be able to recreate this with another layer with a lower alpha value.

Here is what it would look like.

var drawingLayer = CAShapeLayer()
func drawLines(fromPoint: CGPoint, toPoint: CGPoint) {
    let mutable = CGMutablePath()
    mutable.move(to: fromPoint)
    mutable.addline(to: toPoint)
    drawingLayer.path = mutable
    drawingLayer.fillColor = nil
    drawingLayer.lineCap = kCALineCapRound
    drawingLayer.lineCap = 120 * CGFloat(lineWidthSliderView.value)
    //the bit in your code translated the whole thing to Int before translating it to a 
    //CGFloat, this is a bad idea since Ints cannot store decimals, so if there is no 
    //direct conversion, convert it to Double or Float
    drawingLayer.strokeColor = UIColor(calibratedRed: red/255, green: green/255, blue: blue/255 , alpha: 1).cgColor

}

Somewhere you would also need to do imageEditingView.addSubLayer(drawingLayer)

also, you don't need to convert a CGPoint into another CGPoint, when you do context.move(to:) and other places...

C1FR1
  • 133
  • 1
  • 9
  • 1
    Thank you so much! This solved the problem, but when I use UIImageWriteToSavedPhotosAlbum, it only saved the image, it doesn't save the drawing on the drawingLayer. How to save the image with the drawingLayer on it?? – Bryce Chan Nov 13 '16 at 09:09
  • 1
    I've found the solution, by passing the image to another variable and save it. Thanks again! – Bryce Chan Nov 13 '16 at 10:11