9

So it is known that apple's the images backing Emoji in unicode can be extracted at a resolution as high as 160x160 pixels. There is a tool available that can do this on OS X by pulling the data out of "apple color emoji" font here: https://github.com/tmm1/emoji-extractor

I am interested in extracting/utilizing apple's Emoji images in a similar way on iOS, I found the following solution and really like the implementation here: https://stackoverflow.com/a/38809531/4556704

extension String {
func image() -> UIImage {
    let size = CGSize(width: 30, height: 35)
    UIGraphicsBeginImageContextWithOptions(size, false, 0);
    UIColor.whiteColor().set()
    let rect = CGRect(origin: CGPointZero, size: size)
    UIRectFill(CGRect(origin: CGPointZero, size: size))
    (self as NSString).drawInRect(rect, withAttributes: [NSFontAttributeName: UIFont.systemFontOfSize(30)])
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}

}

There is a problem, however, that I am running into with this implementation. If I use the string extension above, it is obvious to me that the resulting image is not 160x160 px in resolution. What I mean by that is, I am unable to produce an image of comparable quality to, say, if I were to include a 160x160 image in my project's assets.

What is the reasoning for this, and can I solve this problem without importing upwards of 1700 emoji images to my project? I figure that the font on iOS must still contain the data necessary to produce 160x160 image samples. The String extension is ideal as it allows me to reference the emoji characters more freely than if I were to simple import all these images.

I figure this may require some low level code that could be way more trouble than it's worth, but I really would love to know more about the root of this issue and possible fixes. I'm sure this is attributed to apple not rendering the emoji at a level higher than necessary, but surely there is some way to override this. Also I am aware that there are other high resolution Emoji image sets, this question is not about that.

edit: mismatched resolutions

edit 10/18/16: I've come to the conclusion that the issue can be attributed to the fact that the source image being sampled is not of the highest resolution that is assumed to be possible. It seems that the emoji is not being rendered at resolutions higher than 48x48 px, when it has been demonstrated that the emoji images can be rendered up to 160x160 px on OS X, and can be ripped from "Apple Color Emoji.ttf/.ttc" at 160x160 px. I am not sure if there even is a possible solution to this issue, as it seems like a hard limit imposed by how iOS uses unicode character codes that map to png image data.

Community
  • 1
  • 1
Harrison
  • 319
  • 2
  • 14
  • The code you posted will create a 30x35 *point* image. On a non-retina device the image will be 30x35 pixels. On a retina device it will be 60x70 pixels. On a retina HD device it will be 90x105 pixels. – rmaddy Oct 17 '16 at 15:58
  • @rmaddy Thanks for your reply, I understand this for the most part and was mostly inserting that code so that readers didn't have to check that link if they didn't want to. The real problem here is that no matter how I format the sourcing of the Emoji's size in code similar to that posted code(mainly by upping the font size), I am unable to achieve as clear of a resolution image as is attainable using the 160x160px images ripped from my macbook. – Harrison Oct 17 '16 at 16:09
  • Just to say this is still an issue on iOS12. Tried forcing the font to AppleColorEmoji but doesn't seem to make any differences. – Zoë Smith Nov 05 '18 at 12:59

2 Answers2

1

Your issue is that you take a string of a specific font size and then you force it into an area of another specific size. The two might not match resulting in the drawn image being scaled to fit.

Either calculate the size needed for the given string and font or calculate the needed font size to allow the given string to fit into the allotted size.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • always quality answers – David Seek Oct 17 '16 at 16:39
  • @rmaddy, again thank you for your comments/answers. Please take a look at the image I've attached to the main question. You will see I have already taken measures to attempt to scale the image up, but if you look at the image derived from code you will notice the extreme difference in resolution from the image that is ripped from the ttf data using the link found in my original question. The issue is moreso that the – Harrison Oct 17 '16 at 16:44
  • (sorry I accidentally hit enter) ...moreso that the text/string/font engine is limiting the ultimate resolution of the Emoji image. This is happening when we know that the font info contains a high enough resolution image to produce the image opened in preview in my screenshot above. – Harrison Oct 17 '16 at 16:46
  • The code in the image you posted is quite different from the code in your original question. – rmaddy Oct 17 '16 at 16:47
  • Yes, it has been re-arranged so that the resulting image bounds are analogous to the bounds of the input string. Fundamentally it is quite similar. – Harrison Oct 17 '16 at 16:48
  • That new code has many issues. All of the fractional sizes and points will cause all kinds of problems. Make everything integral. – rmaddy Oct 17 '16 at 16:51
  • I understand what you are pushing at, that fractional sizes can affect pixel alignment which may result in "off" images. The issue, still, is that the source image which is being rendered is not of the highest resolution that is assumed to be possible. I have tried making all figures integral. It seems that the emoji is not being rendered past 48x48 px, when it has been demonstrated that the emoji images can be rendered up to 160x160 px. – Harrison Oct 17 '16 at 17:06
1

Replace

UIGraphicsBeginImageContext(rect.size)

or

UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)

with

UIGraphicsBeginImageContextWithOptions(rect.size, false, 3.0)

A scale of 2.0 also works; I can't see a difference between that and 3.0 at a quick glance.

JKaz
  • 765
  • 6
  • 18