Yorma Yorma - 10 months ago 75
iOS Question

Swift 3 - NSString.draw(in: rect, withAttributes:) -- Text not being drawn at expected point

Teeing off of this Stackoverflow post, which was very helpful, I've been able to successfully draw text onto a full-screen image (I'm tagging the image with pre-canned, short strings, e.g., "Trash"). However, the text isn't appearing where I want, which is centered at the exact point the user has tapped. Here's my code, based on some code from the above post but updated for Swift3 --

func addTextToImage(text: NSString, inImage: UIImage, atPoint:CGPoint) -> UIImage{

// Setup the font specific variables
let textColor: UIColor = UIColor.red
let textFont: UIFont = UIFont(name: "Helvetica Bold", size: 80)!

//Setups up the font attributes that will be later used to dictate how the text should be drawn
let textFontAttributes = [
NSFontAttributeName: textFont,
NSForegroundColorAttributeName: textColor,
]

// Create bitmap based graphics context
UIGraphicsBeginImageContextWithOptions(inImage.size, false, 0.0)

//Put the image into a rectangle as large as the original image.
inImage.draw(in: CGRect(x:0, y:0, width:inImage.size.width, height: inImage.size.height))

// Create the rectangle where the text will be written
let rect: CGRect = CGRect(x:atPoint.x, y:atPoint.y, width:inImage.size.width, height: inImage.size.height)

// Draft the text in the rectangle
text.draw(in: rect, withAttributes: textFontAttributes)

// Get the image from the graphics context
let newImag = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

return newImag!
}


In the above, atPoint is the location of the user's tap. This is where I want the text to be drawn. However, the text is always written toward the upper left corner of the image. For example, in the attached image, I have tapped half way down the waterfall as that is where I want the text string "Trash" to be written. But instead, you can see that it is written way up in the left-hand corner. I've tried a bunch of stuff but can't get a solution. I appreciate any help.
enter image description here

TrashShouldBeInMiddleOfWaterfallButIsNot

Answer Source

How are you setting atPoint? If you are using the same coordinate space as the screen, that won't work... which is what I suspect is happening.

Suppose your image is 1000 x 2000, and you are showing it in a UIImageView that is 100 x 200. If you tap at x: 50 y: 100 in the view (at the center), and then send that point to your function, it will draw the text at x: 50 y: 100 of the image -- which will be in the upper-left corner, instead of in the center.

So, you need to convert your point from the Image View size to the actual image size.. either before you call your function, or by modifying your function to handle it.

An example (not necessarily the best way to do it):

    // assume:
    //    View Size is 100 x 200
    //    Image Size is 1000 x 2000
    //    tapPoint is CGPoint(x: 50, y: 100)

    let xFactor = image.size.width / imageView.frame.size.width
    // xFactor now equals 10

    let yFactor = image.size.height / imageView.frame.size.height
    // yFactor now equals 10

    let convertedPoint = CGPoint(x: tapPoint.x * xFactor, y: tapPoint.y * yFactor)

convertedPoint now equals CGPoint(x: 500, y: 1000), and you can send that as the atPoint value in your call to addTextToImage.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download