Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw text in image right corner

Tags:

ios

swift

uiimage

I want to draw a text in the top or bottom right corner of an UIImage. I have an extension which works great to draw the text but the problem is to positioned the text at the right of the screen (because text is cut).

Here is the extension :

extension UIImage {

func addText(drawText: NSString, atPoint: CGPoint, textColor: UIColor?, textFont: UIFont?) -> UIImage{

    // Setup the font specific variables
    var _textColor: UIColor
    if textColor == nil {
        _textColor = UIColor.white
    } else {
        _textColor = textColor!
    }

    var _textFont: UIFont
    if textFont == nil {
        _textFont = UIFont.systemFont(ofSize: 50)
    } else {
        _textFont = textFont!
    }

    // Setup the image context using the passed image
    UIGraphicsBeginImageContext(size)

    // Setup the font attributes that will be later used to dictate how the text should be drawn
    let textFontAttributes = [
        NSFontAttributeName: _textFont,
        NSForegroundColorAttributeName: _textColor,
        ] as [String : Any]

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

    // Create a point within the space that is as bit as the image
    let rect = CGRect(x: atPoint.x, y: atPoint.y, width: size.width, height: size.height)


    // Draw the text into an image
    drawText.draw(in: rect, withAttributes: textFontAttributes)

    // Create a new image out of the images we have created
    let newImage = UIGraphicsGetImageFromCurrentImageContext()

    // End the context now that we have the image we need
    UIGraphicsEndImageContext()

    //Pass the image back up to the caller
    return newImage!
}
}

Problem is if the text is too long or too big it will be out of the screen. I would need to change the origin point to write the text from the right to the left so it will take space only on the left and not on the right out of the screen. How could I do that ?

actual issue

what I want

like image 879
user3722523 Avatar asked Jun 01 '17 11:06

user3722523


1 Answers

There is a simple function call to get the "bounding box" for a string. You can use that to position where the text should be drawn into the image:

    // get the bounding-box for the string
    let stringSize = drawText.size(attributes: textFontAttributes)

    // position the bounding-box at the bottom-right corner of the image
    let x = self.size.width - ceil(stringSize.width)
    let y = self.size.height - ceil(stringSize.height)

    let rect = CGRect(x: x, y: y, width: stringSize.width, height: stringSize.height)

    // Draw the text into an image
    drawText.draw(in: rect, withAttributes: textFontAttributes)

Note that this sample code positions the text at bottom-right corner - ignoring the atPoint parameter. You would likely change that to a whichCorner type parameter, and then calculate the x and y position appropriately.

By the way... drawText is a terrible name for a variable - it sounds like a function. Much more readable to use something like textToDraw.


Here is a modified function, using a atCorner parameter, where the values are:

        +-----------+ 
        | 0       1 | 
        |           | 
        |           | 
        | 3       2 |
        +-----------+

Edit: Using right-aligned paragraph style (as suggested by Thilina Chamin Hewagama) has some advantages. This edited version will even handle text with "\n" embedded line breaks.

extension UIImage {

    func addText(textToDraw: NSString, atCorner: Int, textColor: UIColor?, textFont: UIFont?) -> UIImage {

        // Setup the font specific variables
        var _textColor: UIColor
        if textColor == nil {
            _textColor = UIColor.white
        } else {
            _textColor = textColor!
        }

        var _textFont: UIFont
        if textFont == nil {
            _textFont = UIFont.systemFont(ofSize: 50)
        } else {
            _textFont = textFont!
        }

        // Setup the image context using the passed image
        UIGraphicsBeginImageContext(size)

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

        let titleParagraphStyle = NSMutableParagraphStyle()

        // Setup the font attributes that will be later used to dictate how the text should be drawn
        let textFontAttributes = [
            NSFontAttributeName: _textFont,
            NSForegroundColorAttributeName: _textColor,
            NSParagraphStyleAttributeName: titleParagraphStyle
            ] as [String : Any]

        // get the bounding-box for the string
        var stringSize = textToDraw.size(attributes: textFontAttributes)

        // draw in rect functions like whole numbers
        stringSize.width = ceil(stringSize.width)
        stringSize.height = ceil(stringSize.height)

        var rect = CGRect(origin: CGPoint.zero, size: self.size)

        switch atCorner {

        case 1:
            // top-right
            titleParagraphStyle.alignment = .right

        case 2:
            // bottom-right
            rect.origin.y = self.size.height - stringSize.height
            titleParagraphStyle.alignment = .right

        case 3:
            // bottom-left
            rect.origin.y = self.size.height - stringSize.height

        default:
            // top-left
            // don't need to change anything here
            break

        }

        // Draw the text into an image
        textToDraw.draw(in: rect, withAttributes: textFontAttributes)

        // Create a new image out of the images we have created
        let newImage = UIGraphicsGetImageFromCurrentImageContext()

        // End the context now that we have the image we need
        UIGraphicsEndImageContext()

        //Pass the image back up to the caller
        return newImage!
    }

}
like image 70
DonMag Avatar answered Oct 23 '22 02:10

DonMag