[JavaScript]画像で最も使われている色を枠線の色として設定する

# やりたいこと
画像で最も使われている色（便宜上以下では「メインカラー」で呼ぶ）を枠線に付けたい。

##### 対応前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/2f2d6d43-5248-ecb4-c3bf-29b3c4139f1b.png)

##### 対応後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/fb4efbca-7619-99f3-0a59-ffaabb4219de.png)

左側の画像は単色のため、分かりにくいですが、
ちゃんと枠線がついています。


# TL;DR
RGBasterというライブラリを利用する。

実装
* [HTML](#html)
* [JavaScript](#コード)

# 調査

やりたいことに対して、参考できる記事やサイトがないかを検索してみます。

それっぽいキーワードで検索したところ、下記のQiita記事がヒットしました。

https://qiita.com/kenzooooo/items/6439ae650f31b6b9853f

こちらの記事では、[jquery.adaptive-backgrounds.js](https://github.com/briangonzalez/jquery.adaptive-backgrounds.js)というプラグインを利用しているが、今回はjQueryを使いたくなかったです。
どうしようかと思いながらREADMEを読み進むと、別のライブラリを利用していることを判明しました。

> **Credit**
> This plugin is built on top of a script called RGBaster.

早速RGBasterへ移動します。
READMEのリンクは古かったようなので、npmのリンクを貼っておきます。

https://github.com/briangonzalez/rgbaster.js

https://www.npmjs.com/package/rgbaster

画像に含まれている色を面積の大きい順に教えてくれるライブラリです。
Canvasに画像を貼り付けて、ピクセルごとのデータをループして、色コードのカウントをする…という仕組みです。
旧バージョンのものではありますが、RGBasterの仕組みを説明する記事がありましたので、
詳細はそちらを参考してください。
[rgbaster.jsを使って画像の色を抽出してみよう](https://liginc.co.jp/web/js/other-js/130257)

# 実行結果

今回使う3枚のサンプル画像に対し、RGBasterを使ってみました。
以下は結果です。（結構長い）

**画像1**
![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/a17f75c3-2ac1-d751-b2e7-201c56942872.png)
画像1の実行結果
```json
[{"color":"rgb(255,164,97)","count":10000}]
```

**画像2**
![img2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/fe510354-c47b-8f29-8ba8-711d4dbd2fae.png)

<details><summary>画像2の実行結果</summary>

```json
[
    {"color":"rgb(0,0,0)","count":7653},
    {"color":"rgb(239,243,177)","count":1988},
    {"color":"rgb(29,30,22)","count":14},
    {"color":"rgb(104,106,77)","count":14},
    {"color":"rgb(89,91,66)","count":11},
    {"color":"rgb(1,1,1)","count":9},
    {"color":"rgb(52,52,38)","count":9},
    {"color":"rgb(149,152,110)","count":9},
    {"color":"rgb(40,41,30)","count":8},
    {"color":"rgb(215,218,159)","count":8},
    {"color":"rgb(221,225,164)","count":8},
    {"color":"rgb(18,18,13)","count":7},
    {"color":"rgb(216,219,160)","count":7},
    {"color":"rgb(110,112,81)","count":6},
    {"color":"rgb(7,7,5)","count":6},
    {"color":"rgb(44,45,33)","count":6},
    {"color":"rgb(27,28,20)","count":5},
    {"color":"rgb(200,203,148)","count":5},
    {"color":"rgb(206,210,153)","count":5},
    {"color":"rgb(227,231,168)","count":5},
    {"color":"rgb(112,113,83)","count":5},
    {"color":"rgb(8,9,6)","count":5},
    {"color":"rgb(194,197,144)","count":5},
    {"color":"rgb(224,228,166)","count":5},
    {"color":"rgb(73,74,54)","count":4},
    {"color":"rgb(52,53,39)","count":4},
    {"color":"rgb(17,17,12)","count":4},
    {"color":"rgb(218,222,162)","count":4},
    {"color":"rgb(213,216,158)","count":4},
    {"color":"rgb(228,232,169)","count":4},
    {"color":"rgb(13,13,10)","count":4},
    {"color":"rgb(5,5,3)","count":4},
    {"color":"rgb(205,209,152)","count":4},
    {"color":"rgb(238,242,176)","count":4},
    {"color":"rgb(171,173,126)","count":4},
    {"color":"rgb(12,12,9)","count":4},
    {"color":"rgb(236,240,175)","count":4},
    {"color":"rgb(116,118,86)","count":4},
    {"color":"rgb(219,223,162)","count":4},
    {"color":"rgb(33,33,24)","count":4},
    {"color":"rgb(201,205,149)","count":4},
    {"color":"rgb(157,159,116)","count":4},
    {"color":"rgb(134,136,99)","count":4},
    {"color":"rgb(209,213,155)","count":4},
    {"color":"rgb(187,190,138)","count":4},
    {"color":"rgb(37,37,27)","count":4},
    {"color":"rgb(22,22,16)","count":4},
    {"color":"rgb(145,148,108)","count":3},
    {"color":"rgb(146,149,108)","count":3},
    {"color":"rgb(90,91,67)","count":3},
    {"color":"rgb(222,226,164)","count":3},
    {"color":"rgb(56,57,42)","count":3},
    {"color":"rgb(119,121,88)","count":3},
    {"color":"rgb(82,83,60)","count":3},
    {"color":"rgb(217,221,161)","count":2},
    {"color":"rgb(181,184,134)","count":2},
    {"color":"rgb(109,111,80)","count":2},
    {"color":"rgb(152,154,112)","count":2},
    {"color":"rgb(153,155,113)","count":2},
    {"color":"rgb(97,99,72)","count":2},
    {"color":"rgb(35,35,26)","count":2},
    {"color":"rgb(148,151,110)","count":2},
    {"color":"rgb(91,92,67)","count":2},
    {"color":"rgb(144,147,107)","count":2},
    {"color":"rgb(54,55,40)","count":2},
    {"color":"rgb(115,117,85)","count":2},
    {"color":"rgb(59,60,44)","count":2},
    {"color":"rgb(42,43,31)","count":2},
    {"color":"rgb(34,34,25)","count":2},
    {"color":"rgb(20,20,15)","count":2},
    {"color":"rgb(21,21,15)","count":2},
    {"color":"rgb(197,200,146)","count":2},
    {"color":"rgb(207,211,153)","count":2},
    {"color":"rgb(32,32,24)","count":2},
    {"color":"rgb(41,42,31)","count":2},
    {"color":"rgb(50,51,37)","count":2},
    {"color":"rgb(169,172,125)","count":2},
    {"color":"rgb(167,170,124)","count":2},
    {"color":"rgb(14,14,10)","count":2},
    {"color":"rgb(15,15,11)","count":2},
    {"color":"rgb(210,213,156)","count":2},
    {"color":"rgb(28,29,21)","count":2},
    {"color":"rgb(7,8,6)","count":2},
    {"color":"rgb(63,64,47)","count":2},
    {"color":"rgb(62,63,46)","count":2},
    {"color":"rgb(37,38,28)","count":2},
    {"color":"rgb(183,186,135)","count":1},
    {"color":"rgb(159,162,118)","count":1},
    {"color":"rgb(161,164,119)","count":1},
    {"color":"rgb(147,150,109)","count":1},
    {"color":"rgb(192,195,142)","count":1},
    {"color":"rgb(217,220,160)","count":1},
    {"color":"rgb(190,193,141)","count":1},
    {"color":"rgb(51,51,37)","count":1},
    {"color":"rgb(231,235,171)","count":1},
    {"color":"rgb(97,98,71)","count":1},
    {"color":"rgb(74,75,55)","count":1},
    {"color":"rgb(4,4,3)","count":1},
    {"color":"rgb(201,204,149)","count":1},
    {"color":"rgb(60,61,44)","count":1},
    {"color":"rgb(24,25,18)","count":1},
    {"color":"rgb(225,229,167)","count":1},
    {"color":"rgb(204,208,151)","count":1},
    {"color":"rgb(86,88,64)","count":1},
    {"color":"rgb(23,24,17)","count":1},
    {"color":"rgb(182,185,135)","count":1}
]
```
</details>

**画像3**
![img3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/cfa20817-8576-bcc3-6dce-70ad42a50569.png)
<details><summary>画像3の実行結果</summary>

```json
[
    {"color":"rgb(0,255,255)","count":199},
    {"color":"rgb(0,255,253)","count":99},
    {"color":"rgb(0,254,255)","count":98},
    {"color":"rgb(0,255,251)","count":98},
    {"color":"rgb(0,252,255)","count":97},
    {"color":"rgb(0,255,247)","count":97},
    {"color":"rgb(0,249,255)","count":96},
    {"color":"rgb(0,255,243)","count":96},
    {"color":"rgb(0,245,255)","count":95},
    {"color":"rgb(0,255,238)","count":95},
    {"color":"rgb(0,240,255)","count":94},
    {"color":"rgb(0,255,233)","count":94},
    {"color":"rgb(0,233,255)","count":93},
    {"color":"rgb(0,255,226)","count":93},
    {"color":"rgb(0,225,255)","count":92},
    {"color":"rgb(0,255,219)","count":92},
    {"color":"rgb(0,216,255)","count":91},
    {"color":"rgb(0,255,211)","count":91},
    {"color":"rgb(0,207,255)","count":90},
    {"color":"rgb(0,255,201)","count":90},
    {"color":"rgb(0,197,255)","count":89},
    {"color":"rgb(0,255,192)","count":89},
    {"color":"rgb(0,187,255)","count":88},
    {"color":"rgb(0,255,182)","count":88},
    {"color":"rgb(0,176,255)","count":87},
    {"color":"rgb(0,255,172)","count":87},
    {"color":"rgb(0,164,255)","count":86},
    {"color":"rgb(0,255,162)","count":86},
    {"color":"rgb(0,152,255)","count":85},
    {"color":"rgb(0,255,151)","count":85},
    {"color":"rgb(0,140,255)","count":84},
    {"color":"rgb(0,255,140)","count":84},
    {"color":"rgb(0,125,255)","count":83},
    {"color":"rgb(0,255,129)","count":83},
    {"color":"rgb(0,113,255)","count":82},
    {"color":"rgb(0,255,119)","count":82},
    {"color":"rgb(0,101,255)","count":81},
    {"color":"rgb(0,255,106)","count":81},
    {"color":"rgb(0,89,255)","count":80},
    {"color":"rgb(0,255,95)","count":80},
    {"color":"rgb(0,78,255)","count":79},
    {"color":"rgb(0,255,85)","count":79},
    {"color":"rgb(0,67,255)","count":78},
    {"color":"rgb(0,255,75)","count":78},
    {"color":"rgb(0,56,255)","count":77},
    {"color":"rgb(0,255,65)","count":77},
    {"color":"rgb(0,47,255)","count":76},
    {"color":"rgb(0,255,56)","count":76},
    {"color":"rgb(0,37,255)","count":75},
    {"color":"rgb(0,255,47)","count":75},
    {"color":"rgb(0,28,255)","count":74},
    {"color":"rgb(0,255,39)","count":74},
    {"color":"rgb(0,21,255)","count":73},
    {"color":"rgb(0,255,31)","count":73},
    {"color":"rgb(0,14,255)","count":72},
    {"color":"rgb(0,255,23)","count":72},
    {"color":"rgb(0,9,255)","count":71},
    {"color":"rgb(0,255,17)","count":71},
    {"color":"rgb(0,5,255)","count":70},
    {"color":"rgb(0,255,12)","count":70},
    {"color":"rgb(0,2,255)","count":69},
    {"color":"rgb(0,255,8)","count":69},
    {"color":"rgb(0,1,255)","count":68},
    {"color":"rgb(0,255,5)","count":68},
    {"color":"rgb(0,0,255)","count":67},
    {"color":"rgb(0,255,2)","count":67},
    {"color":"rgb(1,0,255)","count":66},
    {"color":"rgb(0,255,1)","count":66},
    {"color":"rgb(2,0,255)","count":65},
    {"color":"rgb(0,255,0)","count":65},
    {"color":"rgb(5,0,255)","count":64},
    {"color":"rgb(1,255,0)","count":64},
    {"color":"rgb(8,0,255)","count":63},
    {"color":"rgb(2,255,0)","count":63},
    {"color":"rgb(12,0,255)","count":62},
    {"color":"rgb(5,255,0)","count":62},
    {"color":"rgb(17,0,255)","count":61},
    {"color":"rgb(8,255,0)","count":61},
    {"color":"rgb(255,255,0)","count":61},
    {"color":"rgb(23,0,255)","count":60},
    {"color":"rgb(13,255,0)","count":60},
    {"color":"rgb(30,0,255)","count":59},
    {"color":"rgb(18,255,0)","count":59},
    {"color":"rgb(37,0,255)","count":58},
    {"color":"rgb(25,255,0)","count":58},
    {"color":"rgb(47,0,255)","count":57},
    {"color":"rgb(32,255,0)","count":57},
    {"color":"rgb(55,0,255)","count":56},
    {"color":"rgb(40,255,0)","count":56},
    {"color":"rgb(65,0,255)","count":55},
    {"color":"rgb(50,255,0)","count":55},
    {"color":"rgb(74,0,255)","count":54},
    {"color":"rgb(60,255,0)","count":54},
    {"color":"rgb(84,0,255)","count":53},
    {"color":"rgb(70,255,0)","count":53},
    {"color":"rgb(95,0,255)","count":52},
    {"color":"rgb(80,255,0)","count":52},
    {"color":"rgb(105,0,255)","count":51},
    {"color":"rgb(91,255,0)","count":51},
    {"color":"rgb(116,0,255)","count":50},
    {"color":"rgb(102,255,0)","count":50},
    {"color":"rgb(127,0,255)","count":49},
    {"color":"rgb(113,255,0)","count":49},
    {"color":"rgb(140,0,255)","count":48},
    {"color":"rgb(125,255,0)","count":48},
    {"color":"rgb(151,0,255)","count":47},
    {"color":"rgb(136,255,0)","count":47},
    {"color":"rgb(161,0,255)","count":46},
    {"color":"rgb(150,255,0)","count":46},
    {"color":"rgb(172,0,255)","count":45},
    {"color":"rgb(161,255,0)","count":45},
    {"color":"rgb(182,0,255)","count":44},
    {"color":"rgb(172,255,0)","count":44},
    {"color":"rgb(191,0,255)","count":43},
    {"color":"rgb(183,255,0)","count":43},
    {"color":"rgb(200,0,255)","count":42},
    {"color":"rgb(193,255,0)","count":42},
    {"color":"rgb(209,0,255)","count":41},
    {"color":"rgb(202,255,0)","count":41},
    {"color":"rgb(219,0,255)","count":40},
    {"color":"rgb(211,255,0)","count":40},
    {"color":"rgb(226,0,255)","count":39},
    {"color":"rgb(220,255,0)","count":39},
    {"color":"rgb(232,0,255)","count":38},
    {"color":"rgb(229,255,0)","count":38},
    {"color":"rgb(238,0,255)","count":37},
    {"color":"rgb(235,255,0)","count":37},
    {"color":"rgb(243,0,255)","count":36},
    {"color":"rgb(241,255,0)","count":36},
    {"color":"rgb(247,0,255)","count":35},
    {"color":"rgb(246,255,0)","count":35},
    {"color":"rgb(251,0,255)","count":34},
    {"color":"rgb(250,255,0)","count":34},
    {"color":"rgb(253,0,255)","count":33},
    {"color":"rgb(252,255,0)","count":33},
    {"color":"rgb(254,0,255)","count":32},
    {"color":"rgb(254,255,0)","count":32},
    {"color":"rgb(255,0,255)","count":31},
    {"color":"rgb(255,0,254)","count":30},
    {"color":"rgb(255,0,252)","count":29},
    {"color":"rgb(255,253,0)","count":29},
    {"color":"rgb(255,0,249)","count":28},
    {"color":"rgb(255,250,0)","count":28},
    {"color":"rgb(255,0,244)","count":27},
    {"color":"rgb(255,246,0)","count":27},
    {"color":"rgb(255,0,238)","count":26},
    {"color":"rgb(255,241,0)","count":26},
    {"color":"rgb(255,0,231)","count":25},
    {"color":"rgb(255,235,0)","count":25},
    {"color":"rgb(255,0,223)","count":24},
    {"color":"rgb(255,228,0)","count":24},
    {"color":"rgb(255,0,214)","count":23},
    {"color":"rgb(255,220,0)","count":23},
    {"color":"rgb(255,0,201)","count":22},
    {"color":"rgb(255,211,0)","count":22},
    {"color":"rgb(255,0,190)","count":21},
    {"color":"rgb(255,201,0)","count":21},
    {"color":"rgb(255,0,179)","count":20},
    {"color":"rgb(255,189,0)","count":20},
    {"color":"rgb(255,0,167)","count":19},
    {"color":"rgb(255,178,0)","count":19},
    {"color":"rgb(255,0,154)","count":18},
    {"color":"rgb(255,166,0)","count":18},
    {"color":"rgb(255,0,141)","count":17},
    {"color":"rgb(255,155,0)","count":17},
    {"color":"rgb(255,0,128)","count":16},
    {"color":"rgb(255,142,0)","count":16},
    {"color":"rgb(255,0,115)","count":15},
    {"color":"rgb(255,130,0)","count":15},
    {"color":"rgb(255,0,100)","count":14},
    {"color":"rgb(255,118,0)","count":14},
    {"color":"rgb(255,0,87)","count":13},
    {"color":"rgb(255,106,0)","count":13},
    {"color":"rgb(255,0,75)","count":12},
    {"color":"rgb(255,92,0)","count":12},
    {"color":"rgb(255,0,63)","count":11},
    {"color":"rgb(255,80,0)","count":11},
    {"color":"rgb(255,0,52)","count":10},
    {"color":"rgb(255,69,0)","count":10},
    {"color":"rgb(255,0,42)","count":9},
    {"color":"rgb(255,58,0)","count":9},
    {"color":"rgb(255,0,33)","count":8},
    {"color":"rgb(255,48,0)","count":8},
    {"color":"rgb(255,0,25)","count":7},
    {"color":"rgb(255,39,0)","count":7},
    {"color":"rgb(255,0,18)","count":6},
    {"color":"rgb(255,31,0)","count":6},
    {"color":"rgb(255,0,11)","count":5},
    {"color":"rgb(255,23,0)","count":5},
    {"color":"rgb(255,0,6)","count":4},
    {"color":"rgb(255,17,0)","count":4},
    {"color":"rgb(255,0,3)","count":3},
    {"color":"rgb(255,10,0)","count":3},
    {"color":"rgb(255,0,1)","count":2},
    {"color":"rgb(255,6,0)","count":2},
    {"color":"rgb(255,0,0)","count":1},
    {"color":"rgb(255,3,0)","count":1}
]
```
</details>

# HTML
```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>App</title>
  </head>
  <body>
    <div id="app" style="place-items: center; min-height: 100vh; display: flex;">
      <div style="width: 80vw">
        <div style="display: flex; justify-content: space-evenly;">
          <img id="img1" src="/img1.png" />
          <img id="img2" src="/img2.png" />
          <img id="img3" src="/img3.png" />
        </div>
      </div>
    </div>
    <script type="module" src="/main.js"></script>
  </body>
</html>
```
とりあえず3枚の画像が横並びするHTMLファイルを用意します。

# 実装
RGBasterの利用は至って簡単です。
```javascript
// ライブラリをインポートする
import analyze from "rgbaster";

// 結果を算出
const result = await analyze("/sample.png");  // 画像ファイルのパスを記載

// メインカラーを取得
const mainColor = result[0].color; // ⇨ "rgb(255,164,97)"
```

枠線の設定も特に難しくありません。
```javascript
// Idを指定して要素を取得
const img = document.getElementById("imgId");
// ボーダーにお好みのスタイルと先ほど取得したメインカラーを設定
img.style.border = `thick solid ${mainColor}`;
```


# コード
3枚の画像を考慮し、全部合わせるとこうなります。
これで冒頭の[対応後](#対応後)の表示になります。

```javascript
import analyze from "rgbaster";

for (let i = 1; i <= 3; i++) {
  const id = `img${i}`;
  const result = await analyze(`/${id}.png`);

  if (result.length) {
    const borderColor = result[0].color;
    const img = document.getElementById(id);
    img.style.border = `thick solid ${borderColor}`;
  }
}
```