Convert Apple Emoji (String) to UIImage
Asked Answered
M

9

60

I need all Apple Emojis.
I can get all the emojis and put them into a String by copying them from the site getemoji but in my app i need the emojis in the right order as images.

Is there a nice way to convert the emojis I copy into a String to a UIImage?
Or a better solution to get all the Apple emojis in the right order?

Myers answered 6/8, 2016 at 22:51 Comment(0)
R
29

Here's an updated answer with the following changes:

Swift 5

import UIKit
extension String {
    func textToImage() -> UIImage? {
        let nsString = (self as NSString)
        let font = UIFont.systemFont(ofSize: 1024) // you can change your font size here
        let stringAttributes = [NSAttributedString.Key.font: font]
        let imageSize = nsString.size(withAttributes: stringAttributes)

        UIGraphicsBeginImageContextWithOptions(imageSize, false, 0) //  begin image context
        UIColor.clear.set() // clear background
        UIRectFill(CGRect(origin: CGPoint(), size: imageSize)) // set rect size
        nsString.draw(at: CGPoint.zero, withAttributes: stringAttributes) // draw text within rect
        let image = UIGraphicsGetImageFromCurrentImageContext() // create image from context
        UIGraphicsEndImageContext() //  end image context

        return image ?? UIImage()
    }
}

Swift 3.2

import UIKit
extension String {
    func textToImage() -> UIImage? {
        let nsString = (self as NSString)
        let font = UIFont.systemFont(ofSize: 1024) // you can change your font size here
        let stringAttributes = [NSFontAttributeName: font]
        let imageSize = nsString.size(attributes: stringAttributes)

        UIGraphicsBeginImageContextWithOptions(imageSize, false, 0) //  begin image context
        UIColor.clear.set() // clear background
        UIRectFill(CGRect(origin: CGPoint(), size: imageSize)) // set rect size
        nsString.draw(at: CGPoint.zero, withAttributes: stringAttributes) // draw text within rect
        let image = UIGraphicsGetImageFromCurrentImageContext() // create image from context
        UIGraphicsEndImageContext() //  end image context

        return image ?? UIImage()
    }
}
Rania answered 25/3, 2019 at 13:51 Comment(2)
Why are you returning an optional extension String { func textToImage() -> UIImage? { if you have a default empty image return image ?? UIImage() – Feaster
Got an Objective-C version of this? – Florella
Z
108

Updated for Swift 4.1

Add this extension to your project

import UIKit

extension String {
    func image() -> UIImage? {
        let size = CGSize(width: 40, height: 40)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        UIColor.white.set()
        let rect = CGRect(origin: .zero, size: size)
        UIRectFill(CGRect(origin: .zero, size: size))
        (self as AnyObject).draw(in: rect, withAttributes: [.font: UIFont.systemFont(ofSize: 40)])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

The code above draws the current String to an Image Context with a white background color and finally transform it into a UIImage.

Now you can write

enter image description here

Example

Given a list of ranges indicating the unicode values of the emoji symbols

let ranges = [0x1F601...0x1F64F, 0x2702...0x27B0]

you can transform it into a list of images

let images = ranges
    .flatMap { $0 }
    .compactMap { Unicode.Scalar($0) }
    .map(Character.init)
    .compactMap { String($0).image() }

Result:

enter image description here

I cannot guarantee the list of ranges is complete, you'll need to search for it by yourself πŸ˜‰

Zohar answered 6/8, 2016 at 23:14 Comment(8)
@Danny182: Please see my update. Next time please create a new question if you have more requests. – Zohar
with the ranges won't work because they would be all mixed (the new ones have strange unicode). I have all the emojis in a array[String] @appzYourLife – Myers
But this is not vector based graphics anymore – Morganstein
Is it possible to make background transparent? – Kristelkristen
Set the drawing origin to CGPoint(x: 2, y: -1) and the font size to 34 and the emojis will also be centered and fit into the image – Took
@Kristelkristen : Did you try UIColor.clear.set() instead of UIColor.white.set() ? – Dita
For a 128×128 image, I used 120pt font with the origin at CGPoint(x: 0, y: -5). – Converge
@OleksiiNezhyborets emoji art is bitmap already, so nothing is actually lost (apart from resolution) – Impropriety
R
29

Here's an updated answer with the following changes:

Swift 5

import UIKit
extension String {
    func textToImage() -> UIImage? {
        let nsString = (self as NSString)
        let font = UIFont.systemFont(ofSize: 1024) // you can change your font size here
        let stringAttributes = [NSAttributedString.Key.font: font]
        let imageSize = nsString.size(withAttributes: stringAttributes)

        UIGraphicsBeginImageContextWithOptions(imageSize, false, 0) //  begin image context
        UIColor.clear.set() // clear background
        UIRectFill(CGRect(origin: CGPoint(), size: imageSize)) // set rect size
        nsString.draw(at: CGPoint.zero, withAttributes: stringAttributes) // draw text within rect
        let image = UIGraphicsGetImageFromCurrentImageContext() // create image from context
        UIGraphicsEndImageContext() //  end image context

        return image ?? UIImage()
    }
}

Swift 3.2

import UIKit
extension String {
    func textToImage() -> UIImage? {
        let nsString = (self as NSString)
        let font = UIFont.systemFont(ofSize: 1024) // you can change your font size here
        let stringAttributes = [NSFontAttributeName: font]
        let imageSize = nsString.size(attributes: stringAttributes)

        UIGraphicsBeginImageContextWithOptions(imageSize, false, 0) //  begin image context
        UIColor.clear.set() // clear background
        UIRectFill(CGRect(origin: CGPoint(), size: imageSize)) // set rect size
        nsString.draw(at: CGPoint.zero, withAttributes: stringAttributes) // draw text within rect
        let image = UIGraphicsGetImageFromCurrentImageContext() // create image from context
        UIGraphicsEndImageContext() //  end image context

        return image ?? UIImage()
    }
}
Rania answered 25/3, 2019 at 13:51 Comment(2)
Why are you returning an optional extension String { func textToImage() -> UIImage? { if you have a default empty image return image ?? UIImage() – Feaster
Got an Objective-C version of this? – Florella
C
12

Same thing for Swift 4:

extension String {
    func emojiToImage() -> UIImage? {
        let size = CGSize(width: 30, height: 35)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        UIColor.white.set()
        let rect = CGRect(origin: CGPoint(), size: size)
        UIRectFill(rect)
        (self as NSString).draw(in: rect, withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 30)])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}
Chromolithograph answered 7/11, 2017 at 17:58 Comment(0)
A
9

Updated @Luca Angeletti answer for Swift 3.0.1

extension String {

    func image() -> UIImage? {
        let size = CGSize(width: 30, height: 35)
        UIGraphicsBeginImageContextWithOptions(size, false, 0);
        UIColor.white.set()
        let rect = CGRect(origin: CGPoint(), size: size)
        UIRectFill(CGRect(origin: CGPoint(), size: size))
        (self as NSString).draw(in: rect, withAttributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 30)])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }

}
Apples answered 7/12, 2016 at 15:45 Comment(0)
B
7

Swift 4.2

I really liked @Luca Angeletti solution. I hade the same question as @jonauz about transparent background. So with this small modification you get the same thing but with clear background color.

I didn't have the rep to answer in a comment.

import UIKit

extension String {
    func emojiToImage() -> UIImage? {
        let size = CGSize(width: 30, height: 35)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        UIColor.clear.set()
        let rect = CGRect(origin: CGPoint(), size: size)
        UIRectFill(CGRect(origin: CGPoint(), size: size))
        (self as NSString).draw(in: rect, withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 30)])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}
Blacktail answered 23/6, 2018 at 7:52 Comment(0)
H
7

Swift 5: ( with optional fontSize, imageSize and bgColor)

use it like this:

let image      = "🀣".image()
let imageLarge = "🀣".image(fontSize:100)
let imageBlack = "🀣".image(fontSize:100, bgColor:.black)
let imageLong  = "🀣".image(fontSize:100, imageSize:CGSize(width:500,height:100))

import UIKit

extension String
{
    func image(fontSize:CGFloat = 40, bgColor:UIColor = UIColor.clear, imageSize:CGSize? = nil) -> UIImage?
    {
        let font = UIFont.systemFont(ofSize: fontSize)
        let attributes = [NSAttributedString.Key.font: font]
        let imageSize = imageSize ?? self.size(withAttributes: attributes)

        UIGraphicsBeginImageContextWithOptions(imageSize, false, 0)
        bgColor.set()
        let rect = CGRect(origin: .zero, size: imageSize)
        UIRectFill(rect)
        self.draw(in: rect, withAttributes: [.font: font])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}
Hussite answered 5/3, 2020 at 5:10 Comment(2)
In your answer emoji is not centered – Chilly
@VitalikKizlov Refer to my answer for this and feel free (you or this answer's author Jolly Jinx) to edit this Swift5 answer based on mine. Use draw(at:withAttributes:) instead of draw(in:withAttributes:). – Rania
P
3

Updated version of @Luca Angeletti's answer using UIGraphicsImageRenderer:

extension String {
    func image() -> UIImage? {
        let size = CGSize(width: 100, height: 100)
        let rect = CGRect(origin: CGPoint(), size: size)
        return UIGraphicsImageRenderer(size: size).image { (context) in
            (self as NSString).draw(in: rect, withAttributes: [.font : UIFont.systemFont(ofSize: 100)])
        }
    }
}
Psia answered 23/6, 2019 at 7:57 Comment(0)
G
2

It's actually much simpler than suggested answers.

extension String {
    func image(pointSize: CGFloat, backgroundColor: UIColor = .clear) -> UIImage {
        let font = UIFont.systemFont(ofSize: pointSize)
        let emojiSize = self.size(withAttributes: [.font: font])

        return UIGraphicsImageRenderer(size: emojiSize).image { context in
            backgroundColor.setFill()
            context.fill(CGRect(origin: .zero, size: emojiSize))
            self.draw(at: .zero, withAttributes: [.font: font])
        }
    }
}

Screenshot from playground

Grape answered 20/8, 2023 at 17:47 Comment(0)
I
1

This variation is based on @Luca's accepted answer, but allows you to optionally customize the point size of the font, should result in a centered image, and doesn't make the background color white.

extension String {
    func image(pointSize: CGFloat = UIFont.systemFontSize) -> UIImage? {
        let nsString = self as NSString
        let font = UIFont.systemFont(ofSize: pointSize)

        let size = nsString.size(withAttributes: [.font: font])
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        let rect = CGRect(origin: .zero, size: size)
        nsString.draw(in: rect, withAttributes: [.font: font])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}
Impropriety answered 1/12, 2019 at 21:45 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.