While Drawing image size Gets changed (Swift)

  func drawLines(fromPoint:CGPoint, toPoint: CGPoint){
     
        if DrawingActive == true{
        UIGraphicsBeginImageContext(self.view.frame.size)
        ImageView.image?.draw(in: CGRect(x: 0, y: 0, width: ImageView.frame.width, height: ImageView.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(fontSizeOfDraw)
        context?.setStrokeColor(DrawingColor.cgColor)
     
        context?.strokePath()
     
        ImageView.image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
     
        PickSize.isEnabled = false
        PickSize.alpha = 0
        ColorPickerController.isEnabled = false
        ColorPickerController.alpha = 0
        DrawBtn.isEnabled = false
        DrawBtn.alpha = 0
            SelectButton.isEnabled = false
            SelectButton.alpha = 0
        }
    }


    func slideDown(fromPoint:CGPoint, toPoint: CGPoint){
     
     
     
     
     
     
     
     
     
    }


    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
     
        swiped = true
     
        if let touch = touches.first{
         
         
            let currentPoint = touch.location(in: self.view)
            drawLines(fromPoint: lastPoint, toPoint: currentPoint)
         
         
            lastPoint = currentPoint
         
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if !swiped{
         
         
        }
     
        drawLines(fromPoint: lastPoint, toPoint: lastPoint)
        PickSize.isEnabled = true
        PickSize.alpha = 1
        ColorPickerController.isEnabled = true
        ColorPickerController.alpha = 1
        DrawBtn.isEnabled = true
        DrawBtn.alpha = 1
        SelectButton.isEnabled = true
        SelectButton.alpha = 0.75
    }



Hello I have this code, my Problem is, that if i try to draw on an image (ImageView) the imageview gets stretched

The image gets stretched, because that's what you asked for:


        ImageView.image?.draw(in: CGRect(x: 0, y: 0, width: ImageView.frame.width, height: ImageView.frame.height))


You've specified the size of the view, not the image, so the image is scaled to the size you asked for. Presumably you want to scale the image to fit the image view somehow (e.g. aspect fit or aspect fill), so you'll have to calculate the scale from the relationship between the image size and the view size.


Also, I suggest you don't use "UIGraphicsBeginImageContext", but do this instead:


        UIGraphicsBeginImageContextWithOptions(self.view.frame.size, true, 0)


Specifying the final parameter ensures that drawing uses the screen (retina) scaling factor of 2x or 3x, otherwise you'll effectively be drawing at 1x, which won't look as good.


Also, I suggest you don't use "view.frame" since it's the wrong coordinate system for drawing in the view, which is what you're doing ultimately. (The frame coordinates are the drawing (bounds) coordinates of the superview.) Also, if a view has a transform applied to it, the "frame" property is undefined. Use "view.bounds" instead.


Also, I strong recommend you don't do things like this in Swift:


        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(fontSizeOfDraw)
        context?.setStrokeColor(DrawingColor.cgColor)
     
        context?.strokePath()


Propagating an optional this way doesn't make sense, because "context" isn't effectively optional here. If it was nil, your code would just misbehave in mysterious ways. Better to handle the optional resolution immedately:


        let context = UIGraphicsGetCurrentContext()! // <- resolve the optional
     
        context.move(to: CGPoint(x: fromPoint.x, y: fromPoint.y))
        context.addLine(to: CGPoint(x: toPoint.x, y: toPoint.y))
        …


In this case, since the context really cannot turn out to be nil, you can go ahead and use the "!" operator. (If it ever turns out to be nil, something in your app has gone horribly wrong, and the sooner it aborts the better.)


Finally, I suggest you follow the normal Swift capitalization rules, which specify an initial cap only for types, and not for properties. So "imageView" not "ImageView", "drawingActive" not "DrawingActive". I realize you might be comfortable with your spellings from conventions in another language, but it really does confuse anyone who has to read your code — ImageView.image looks like a static property of a class named "ImageView", for example.

Any idea how to calculate it

Thank you very much

Handle the X and Y directions separately. Compute the scale factor as "viewSize / imageSize", where the size is height or width. For example, if the view is 150 points wide and the image is 100 points wide, you would need to scale the image by 150/100 or 1.5 to fill the view width.


Then decide whether you want to use the larger of the X and Y scales (to get an "aspect fill" effect that fills the entire view but clips the image) or the smaller of the X and Y scales (to get an "aspect fit" effect that scales the image to fit entirely within the view). Whichever one scale you chose, you'll use it for scaling the image in both the X and Y directions. (That what keeps the aspect ratio.)


Multiply the image width and height by this scale to get the final image size. Using this size for "UIGraphicsBeginImageContext…". Then construct a CGRect whose bottom left is x:0 and y:0 and whose size is this same scaled size. This CGRect is what you use for "draw(in:)".


Note that using this context size means that your drawn-on image may not fill the image view. Use (say) the centering option of the image to place the image appropriately.

Thank yoi very much, would it be to much to schow that in code

Not too much, but this shouldn't be difficult to figure out. It's more logic than math. Something like this (written in post, not checked for errors):


     if DrawingActive, let image = ImageView.image {
          let viewSize = ImageView.bounds.size
          let imageSize = image.size

          let xScale = imageSize.width > 0 ? viewSize.width / imageSize.width : 1
          let yScale = imageSize.height > 0 ? viewSize.height / imageSize.height : 1
          let scale = (xScale > 0 && yScale > 0) ? min (xScale, yScale) : 1 // aspect fit, use "max" for aspect fill
          let scaledSize = CGSize (width: scale * imageSize.width, height: scale * imageSize.height)

          UIGraphicsBeginImageContextWithOptions (scaledSize, true, 0)
          image.draw (in: CGRect(x: 0, y: 0, width: scaledSize.width, height: scaledSize.height))


As you can see, the only tricky part is making sure you don't divide by zero, or use an impossible scale.

Didnt really work for me, like when i draw a line the position is not right

Yeah, because you are trying to avoid understanding what's going on. 😉


With the code I gave you, you would have to adjust the line drawing code too, because now you're drawing into a rectangular area that's the size of the image, not the size of the view. In your original code, the input parameters are in terms of the view.


If you want to draw the lines anywhere in the view (for example, if the lines might extend beyond the image you're drawing on top of), then you will need to use the view size in UIGraphicsBeginImageContextWithOptions, and you will have to compute a different x-y origin for the CGRect you use for "image.draw(in:)".


Under those circumstances, you (presumably) want the center of the image to be at the center of the view, so you need to compute the origin of the rect from the desired center position. (Hint: If you draw a rough picture on a piece of paper, it should be clear what you need to subtract.)

Are you able to show this in code too bcs i have no idea how to do it with draw line

Thank you very much

???

The problem is that (a) I can't just write code for you, and (b) I don't understand which part of this you don't understand.


Can you explain whether these lines are supposed to be limited to just the size of the image (ImageView.image), or can the lines be drawn outside the image too?

I dont understand how to use it in the code, because when i tried it it didnt work

They should be limited to the image

Sorry

OK, assuming that the input coordinates are in terms of the view, and that your image is centered within the image view, think about it this way:


— For convenience, let's set a variable for the view bounds:


     let viewBounds = ImageView.bounds


— The center of the image (in view coordinates) is CGPoint (x: viewBounds.midX, y: viewBounds.midY).


— The origin (bottom left) of the image (in view coordinates) is:


     let imageOrigin = CGPoint (x: viewBounds.midX - imageSize.width / 2, y: viewBounds.midY - imageSize.height / 2)


That is, we back off half the image size to get from its center to its origin.


— The distance from the view origin to the image origin (in view coordinates) is:


     let offset = CGPoint (x: imageOrigin.x - viewBounds.minX, y: imageOrigin.y - viewBounds.minY)


— So that's what you need to add to the input view coordinates to get the desired image context coordinates for the line:


     let fromX = fromPoint.x + offset.x
     let fromY = fromPoint.y + offset.y
     let toX = toPoint.x + offset.x
     let to Y = toPoint.y + offset.y


These are what you need for your moveTo/lineTo calls. (Assuming I haven't made a silly mistake.)

Still not working should i add them in toches moved / ended too?

But thank you very much

And if yes, i tried many ways to do it but it didn't work

My Code looks like this now (I used max, because i have aspect filled)


func drawLines(fromPoint:CGPoint, toPoint: CGPoint){
       
        if DrawingActive == true{
           
           
               
            let image = ImageView.image
            let viewSize = ImageView.bounds.size
            let imageSize = image!.size
           
            let xScale = imageSize.width > 0 ? viewSize.width / imageSize.width : 1
            let yScale = imageSize.height > 0 ? viewSize.height / imageSize.height : 1
            let scale = (xScale > 0 && yScale > 0) ? max (xScale, yScale) : 1 /
            let scaledSize = CGSize (width: scale * imageSize.width, height: scale * imageSize.height)
           
            UIGraphicsBeginImageContextWithOptions (scaledSize, true, 0)
            image?.draw (in: CGRect(x: 0, y: 0, width: scaledSize.width, height: scaledSize.height))
       
           
            let viewBounds = ImageView.bounds
           
            let imageOrigin = CGPoint (x: viewBounds.midX - imageSize.width / 2, y: viewBounds.midY - imageSize.height / 2)
            let offset = CGPoint (x: imageOrigin.x - viewBounds.minX, y: imageOrigin.y - viewBounds.minY)
           
            let fromX = fromPoint.x + offset.x
            let fromY = fromPoint.y + offset.y
            let toX = toPoint.x + offset.x
            let toY = toPoint.y + offset.y
           
        let context = UIGraphicsGetCurrentContext()!
       
        context.move(to: CGPoint(x:fromX, y: fromY))
        context.addLine(to: CGPoint(x: toX ,y: toY))
       
        context.setBlendMode(CGBlendMode.normal)
        context.setLineCap(CGLineCap.round)
        context.setLineWidth(fontSizeOfDraw)
        context.setStrokeColor(DrawingColor.cgColor)
       
        context.strokePath()
           
        ImageView.image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
       
        PickSize.isEnabled = false
        PickSize.alpha = 0
        ColorPickerController.isEnabled = false
        ColorPickerController.alpha = 0
        DrawBtn.isEnabled = false
        DrawBtn.alpha = 0
            SelectButton.isEnabled = false
            SelectButton.alpha = 0
        }
    }
   
   
    func slideDown(fromPoint:CGPoint, toPoint: CGPoint){
       
       
       
       
       
       
       
       
       
    }
   
   
   
   
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
       
       
       
        swiped = true
       
        if let touch = touches.first{
           
       
           
           
            let currentPoint = touch.location(in: self.view)
            drawLines(fromPoint: lastPoint, toPoint: currentPoint)
           
           
            lastPoint = currentPoint
           
        }
    }
   
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if !swiped{
           
           
        }
        if DrawingActive == true{
        drawLines(fromPoint: lastPoint, toPoint: lastPoint)
        PickSize.isEnabled = true
        PickSize.alpha = 1
        ColorPickerController.isEnabled = true
        ColorPickerController.alpha = 1
        DrawBtn.isEnabled = true
        DrawBtn.alpha = 1
        SelectButton.isEnabled = true
            SelectButton.alpha = 0.75
           
        }
    }
While Drawing image size Gets changed (Swift)
 
 
Q