8

For the project I'm working on I need to generate an image file from emoji (ideally Apple emoji). I thought it should be a fairly simple thing, but with each tool I use, I eventually run into a wall.

I've also considered working with an emoji set, like this one that I could query when needed. Unfortunately, the one I've linked to doesn't have Unicode 9.0 emoji such as avocado () shrimp () or harambe (). Do you know of such an up-to-date set?

Code-wise, I've tried opentype.js, but it doesn't support .ttc fonts, which is the extension of the emoji font on my mac (Apple Color Emoji.ttc). I've converted the font to .ttf but that didn't work either:

  var opentype = require('opentype.js');
  opentype.load('./build_scripts/apple_color_emoji.ttf', function (err, font) {
      if (err) {
          alert('Could not load font: ' + err);
      } else {
          console.log("loaded the font",font);

          var Canvas = require('canvas')
            , Image = Canvas.Image
            , canvas = new Canvas(200, 200)
            , ctx = canvas.getContext('2d');
          var path = font.getPath('', 0, 150, 72);
          path.draw(ctx);
          console.log('<img src="' + canvas.toDataURL() + '" />');
      }
  });

The result looks like this:

The result looks like this:

I've tried fontkit, which is supposed to be able to read .ttc files, but it throws an error if I try to use the Apple Color Emoji font.

  var fontkit = require('fontkit');
  var font = fontkit.openSync('./build_scripts/Apple Color Emoji.ttc'); 
  // TypeError: font.layout is not a function

If I try the same with my converted .ttf file I end up with some incorrect svg:

  var fontkit = require('fontkit');
  var font = fontkit.openSync('./build_scripts/apple_color_emoji.ttf');
  var run = font.layout('');
  var svg = run.glyphs[0].path.toSVG();

  console.log(svg);
  // M-1 0ZM799 800Z

My question is, am I even approaching this the right way? Converting emoji that I already have on my machine to a .png or another format seems like something that should be fairly straightforward but I just can't get it to work.

EDIT:

I've found a list of emoji names by their hex codes in this repo (big shoutouts to rodrigopolo). Now I can simply use this:

var emoji = "".codePointAt(0).toString(16); //1f60a
var emojiFile = fs.readFileSync('./my-emoji-folder/' + emoji + '.png');

Still, would be great to know if somebody has a coding solution to this problem!

FURTHER EDIT:

Turns out the first solution I've found only included emoji up to Unicode 8.0, not Unicode 9.0. I've found a ruby gem gemoji that does emoji extraction. If you're not a ruby developer (I'm not), you can simply use the following commands in your shell:

git clone https://github.com/github/gemoji.git
cd gemoji
bundle install
bundle exec gemoji extract some-directory/emoji

You now have Unicode 9.0 emoji in your some-directory/emoji folder!

user2634633
  • 509
  • 8
  • 21
  • That seems like an extremely esoteric problem (+1). Out of curiosity, why exactly do you need to create an image out of emoji? – Dragomok Apr 26 '17 at 15:58
  • 1
    Haha, yeah, might be why I had such a hard time finding a solution. I'm experimenting with a react project where I can change the look of the website by building it with a different .env file. I've decided the favicon to be an emoji so I needed a way to generate them dynamically depending on the emoji specified in .env. But for a more everyday use, you could use it to display the latest emoji on devices that don't support them yet. – user2634633 Apr 26 '17 at 17:35
  • 1
    Who said fontkit supported TTC? Because it absolutely does not. Unpack your TTC to *actual* font files, then use those for image generation instead. Also, if you found a solution don't add that as an "edit", write an answer and then a day later accept it. Questions without answers are just going to get lost to time, instead of google indexed. – Mike 'Pomax' Kamermans May 01 '17 at 00:44
  • It seems so on their docs: https://github.com/devongovett/fontkit – user2634633 May 04 '17 at 13:56
  • How does it works with google indexing? I'm not accepting my own answer because I'm still looking for a non-hacky solution – user2634633 May 04 '17 at 13:59
  • Are you doing this as a one off thing? As in you just need to generate the png(s) once? If so, how about generating them using the canvas API in the browser. You can either write a tiny server to save to or you could run it in [electron](https://electron.github.io) and save directly. – gman May 05 '17 at 15:47
  • @gman I needed it as a part of a build script, but one-off would do as well. Turns out you can do it in regular node, have a look at the accepted answer. – user2634633 May 05 '17 at 20:10

1 Answers1

5

I was able to get this to work with fontkit by selecting a font from the font collection. I haven't found a case yet where using either of the TTFs included in the "Apple Color Emoji.ttc" gives different results.

const fs = require('fs');
const fontkit = require('fontkit');
const emoji = require('node-emoji');
const font = fontkit.openSync('./Apple Color Emoji.ttc').fonts[0];

let emo = emoji.get('100');
let run = font.layout(emo);
let glyph = run.glyphs[0].getImageForSize(128)

fs.writeFileSync('100.png', glyph.data);
  • 1
    Exactly what I was looking for! I'd just remove `node-emoji` dependency for the sake of simplicity: `let run = font.layout('');`. – user2634633 May 05 '17 at 20:04
  • Also, one thing to keep in mind the `getImageForSize` function gets the emoji image in pixels, and it looks like the max size for the Apple Color Emoji is 160. – thebenmiller May 05 '17 at 20:29