🤡

emoji絵文字の色を抽出してみた

2022/06/16に公開

つくってみた

デモ:
https://node-vibrant-example.cubdesign.com/

ソース:
https://github.com/cubdesign/node-vibrant-example

↓ こういうやつ

  • emoji を入力、画像を選択してそれぞれの目立つ色を抽出。
  • 画像はサーバーにアップロードせす、ローカルで処理。
  • 絵文字は apple 系 → apple emoji、Android → Google emoji、他 → twemoji をデバイスによって出しわけ。

しくみ

色の抽出は、画像から目立つのある色を抽出する node.js ライブラリ
node-vibrantを使う。

絵文字をそのままnode-vibrantで扱うことができないので、twemoji-parserを使って、絵文字をコードに変換。コードを元に emoji database の cdn から画像を取得しnode-vibrantで抽出する。

デモでは、抽出した色の中から、トップレートのものを背景色。抽出した色でグラデーションを作り、絵文字の背景としてみた。

1. 絵文字のコードを取得

↓ こういう変換

👾 → 1f47e

🙅🏻‍♂️ → 1f645-1f3fb-200d-2642-fe0f

twemoji-parserでは、コードが直接取得できないので、twemoji-parserで、絵文字の画像を取得して、画像 URL からコードを取得する。

import { EmojiEntity, parse } from "twemoji-parser";

export type Emoji = {
  text: string;
  unicode: string;
  brand: EmojiBrand;
  imageUrl: string;
};

/**
 * 絵文字の画像URLからunicodeテキストを取得する
 *
 * @param emojiImageURL 絵文字の画像URL
 * @returns
 */
const getUnicodeFromEmojiImageURL = (emojiImageURL: string): string => {
  return emojiImageURL.replace(/.*\/(.*)\.(png|svg)/, "$1");
};

/**
 * 絵文字のユニコードを取得する
 *
 * @param emoji 絵文字(複数可)
 */
const getEmojis = (emoji: string, ua: string): Emoji[] => {
  const emojiBrand: EmojiBrand = getEmojiBrandByUA(ua);

  const emojiEntities: EmojiEntity[] = parse(emoji, {
    buildUrl: (codepoints: string, assetType: string): string => {
      return assetType === "png"
        ? `https://cdn.jsdelivr.net/npm/emoji-datasource-${emojiBrand}@14.0.0/img/${emojiBrand}/64/${codepoints}.png`
        : `https://twemoji.maxcdn.com/v/latest/svg/${codepoints}.svg`;
    },
    assetType: "png",
  });

  const emojis: Emoji[] = [];

  for (let i: number = 0; i < emojiEntities.length; i++) {
    const emojiEntity: EmojiEntity = emojiEntities[i];

    emojis.push({
      text: emojiEntity.text,
      unicode: getUnicodeFromEmojiImageURL(emojiEntity.url),
      brand: emojiBrand,
      imageUrl: emojiEntity.url,
    });
  }

  return emojis;
};

2. 絵文字の画像 URL を取得

twemoji-parserで絵文字の画像 URL を作成する。
 画像は、emoji-data の cdn を使用。64x64 の png。

👾 = {
    emojiBrand:  "apple" | "google" | "twitter",
    codepoints: "1f47e"
}

https://cdn.jsdelivr.net/npm/emoji-datasource-${emojiBrand}@14.0.0/img/${emojiBrand}/64/${codepoints}.png
import { EmojiEntity, parse } from "twemoji-parser";

const getEmojiBrandByUA = (ua: string): EmojiBrand => {
  if (isApple(ua)) {
    return "apple";
  }
  if (isAndroid(ua)) {
    return "google";
  }

  // appleデバイス、アンドロイド以外はTwitterとする
  return "twitter";
};

const emojiBrand: EmojiBrand = getEmojiBrandByUA(ua);

const emojiEntities: EmojiEntity[] = parse(emoji, {
  buildUrl: (codepoints: string, assetType: string): string => {
    return assetType === "png"
      ? `https://cdn.jsdelivr.net/npm/emoji-datasource-${emojiBrand}@14.0.0/img/${emojiBrand}/64/${codepoints}.png`
      : `https://twemoji.maxcdn.com/v/latest/svg/${codepoints}.svg`;
  },
  assetType: "png",
});

3. 絵文字の色を抽出

node-vibrantに絵文字画像の URL を渡し色を抽出する。6 色抽出される。

import Vibrant from "node-vibrant";

const palette: Palette = await Vibrant.from(imageURL)
  .quality(quality)
  .getPalette();

はまったこと

worker.jsエラーがめちゃくちゃでて、原因不明で悩んでいたところ、node-vibrantのバージョン問題だった。バージョンを変更したらエラーがでなくなった。(2022.06.16)

"node-vibrant": "^3.2.1-alpha.1" -> "node-vibrant": "^3.1.6"

詳しくは、ここ ↓

https://github.com/Vibrant-Colors/node-vibrant/issues/113

つかったライブラリ

意図した色が抽出される場合と、そうでない時があり、微妙だった。

GitHubで編集を提案

Discussion