Tuesday 5 January 2016

Annotating UIImage (Drawing and writing Text on Image)

Drawing on UIImage


While developing the iOS application we have many scenarios where we have to edit the image to add some custom drawing over it or to add the text over it.  Today we will learn how to do all these functionality. 





For Doing that lets simply create a singleview based project and add a UIImageview on it. Also add some buttons to perform specific actions like drawing ,adding text and saving it to camera roll. 


Now open the view controller and first create a function to add a line between two points. This we will use when we will draw the lines.



func drawLineFrom(fromPoint: CGPoint, toPoint: CGPoint) {
        UIGraphicsBeginImageContext(imgCorrection.frame.size)
        let context = UIGraphicsGetCurrentContext()
        imgCorrection.image?.drawInRect(CGRect(x: 0, y: 0, width: imgCorrection.frame.size.width, height: imgCorrection.frame.size.height))
        CGContextMoveToPoint(context, fromPoint.x, fromPoint.y)
        CGContextAddLineToPoint(context, toPoint.x, toPoint.y)
        CGContextSetLineCap(context, CGLineCap.Round)
        CGContextSetLineWidth(context, pointerWidth)
        CGContextSetRGBStrokeColor(context, 254.0/255.0 , 87.0/255.0,86.0/255.0, 1.0)
        CGContextSetBlendMode(context, CGBlendMode.Normal)
        CGContextStrokePath(context)
        imgCorrection.image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
    }

Now it’s the time to do the drawing for that override the touch methods.

Here I have added the condition to which mode it is currently either in drawing or text. For text mode we will discuss it further.

* Store the first point where user tapped

  override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if editMode == ImageEditModes.editModeDrawing {
            swiped = false
            //store the first point where clicked
            if let touch = touches.first  {
                lastPoint = touch.locationInView(self.view)
            }
        } else if editMode == ImageEditModes.editModeText {
            //store the first point where clicked and unhide the textview if hidden to capture the text
            if let touch = touches.first  {
                lastPoint = touch.locationInView(self.imgCorrection)
            }
            if viewInputText.hidden == true {
                self.viewInputText.hidden = false
                viewInputText.frame = CGRectMake(lastPoint.x, lastPoint.y, viewInputText.frame.size.width, viewInputText.frame.size.height)
                txtCorrection.becomeFirstResponder()
            }
        }
    }
   
* Draw a small continuous line as user moves between the first point and user moved point.   

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if editMode == ImageEditModes.editModeDrawing {
            swiped = true
           
            // Draw a line in the image and display it
            if let touch = touches.first {
                let currentPoint = touch.locationInView(view)
                drawLineFrom(lastPoint, toPoint: currentPoint)
                lastPoint = currentPoint
            }
        }
    }

*Create a image and set it on the UIImageView to display.

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if editMode == ImageEditModes.editModeDrawing {
            if !swiped {
                drawLineFrom(lastPoint, toPoint: lastPoint)
            }
            //Draw the line and create the image to set on the imageview
           
            UIGraphicsBeginImageContext(imgCorrection.frame.size)
            imgCorrection.image?.drawInRect(CGRect(x: 0, y: 0, width: imgCorrection.frame.size.width, height: imgCorrection.frame.size.height), blendMode: CGBlendMode.Normal, alpha: 1.0)
            imgCorrection.image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
        }
    }


Finally now it’s the time to save in on the Gallery. Create a Image from the context and save it to the image roll.

  UIGraphicsBeginImageContext(imgCorrection.bounds.size)
            imgCorrection.image?.drawInRect(CGRect(x: 0, y: 0,
                width: imgCorrection.frame.size.width, height: imgCorrection.frame.size.height))
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)

Now you have completed the drawing part. Just run the app and check the drawing.



Writing text on UIImage

As from the above tutorial we have added the drawing in the UIImage and now it’s the turn to add text also. To implement that we will follow the approach to create the image from the input text and then merge it with the old image.

So let create a view containing the Textview and add it on the  view.

//Create the view for input and add on the self view and hide it.
        let viewInputText = UIView(frame:CGRectMake(0, 0, 33,40))
        viewInputText.backgroundColor = UIColor.blackColor()
        let txtCorrection = UITextView(frame:CGRectMake(5,5,23,30) )
        txtCorrection.delegate = self
        txtCorrection.font = UIFont.systemFontOfSize(11.0)
        txtCorrection.textColor = UIColor.whiteColor()
        txtCorrection.backgroundColor = UIColor.clearColor()
       
        viewInputText.addSubview(txtCorrection)
        self.view.addSubview(viewInputText)
      



After adding the text now we have to save the image on  the camera roll after user have entered the text.

  //Draw the text view to create a imagefrom it
            UIGraphicsBeginImageContextWithOptions(viewInputText.bounds.size, true, 0)
            viewInputText.drawViewHierarchyInRect(viewInputText.bounds, afterScreenUpdates: true)
            let imageWithText = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            
            //create a UIImage from the current context and save it to camera roll.
            UIGraphicsBeginImageContextWithOptions(imgCorrection.bounds.size, true, 0)
           
            imgCorrection.image?.drawInRect(CGRect(x: 0, y: 0,
                width: imgCorrection.frame.size.width, height: imgCorrection.frame.size.height))

            //Draw the text image in the current context to make a single image.
            imageWithText.drawInRect(viewInputText.frame)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            //save image on the camera roll.

            UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)



Now you have done all the things for writing and drawing.

Here is sample project with all the code of the above tutorial.
If you face any issue or have any suggestions,please leave your comment.


12 comments:

  1. Hi Pradeep.. Nice tutorial. Thanks. But while drawing it zooming in my image. Need help

    ReplyDelete
    Replies
    1. Hi Mansai,

      Please check your image aspect ratio it should be scale to fill.

      Also, try to put your image in sample code and check.

      Delete
  2. Thanks Pradeed, very good tutorial but I have one query. Text view background colour always comes as black, can it be cleared?

    ReplyDelete
    Replies
    1. just playing with code, I would able to resolve same.

      UIGraphicsBeginImageContextWithOptions(self.viewLable.bounds.size, false, 0)

      Just set false to opaque instead of true and it worked.

      Delete
  3. You can edit image and make text in device. You can use software to make drawing and writing. Ace Baker Work You can bold, italic, underlie words.

    ReplyDelete