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?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
DanielZanchi
  • 2,708
  • 1
  • 25
  • 37

9 Answers9

105

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

Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
27

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()
    }
}
om-ha
  • 3,102
  • 24
  • 37
  • Why are you returning an optional extension String { func textToImage() -> UIImage? { if you have a default empty image return image ?? UIImage() – Muvimotv May 01 '22 at 19:13
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
    }
}
Daniel
  • 20,420
  • 10
  • 92
  • 149
MrBr
  • 1,884
  • 2
  • 24
  • 38
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
    }

}
Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
Justin Domnitz
  • 3,217
  • 27
  • 34
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
    }
}
Community
  • 1
  • 1
Sebbo
  • 326
  • 4
  • 10
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
    }
}
JollyJinx
  • 119
  • 1
  • 3
  • 1
    In your answer emoji is not centered – Vitalik Kizlov Apr 07 '20 at 12:20
  • @VitalikKizlov Refer to my [answer](https://stackoverflow.com/a/55339365/10830091) 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:)`](https://developer.apple.com/documentation/foundation/nsstring/1533109-draw) instead of `draw(in:withAttributes:)`. – om-ha Apr 07 '20 at 18:54
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)])
        }
    }
}
imas145
  • 1,959
  • 1
  • 23
  • 32
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
    }
}
mredig
  • 1,736
  • 1
  • 16
  • 29
0

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

pronebird
  • 12,068
  • 5
  • 54
  • 82