🐙

MySQLに保存したカラーコードをRGBに変換したいんじゃ

2023/02/13に公開

バックエンドからフロントにRGBの値を返したい時にDBでカラーコード扱う際に試したことをまとめます。

結論

00BFFF49151の文字列(0~F)or数値で格納します。
それをSQLでRGBに変換することで実現します。

環境

# mysql -v
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.21 MySQL Community Server - GPL

用意したテーブル

|id|color_code_int|color_code_string|
|--|--------------|-----------------|
| 1|      16777215|           FFFFFF|
| 2|      16711680|           FF0000|
| 3|         49151|           00BFFF|

10進数でカラーコードを保持する時の注意点

16進数を10進数に変換したいと思います。

SELECT CAST(0x00BFFF AS UNSIGNED);
-- 結果: 49151

00BFFFの10進数表記は49151なので正しく変換されています。
では、49151を元の16進数カラーコードに戻します。

SELECT HEX(49151);
-- 結果: BFFF

頭の00が消えてしまいました。
カラーコードは必ず6桁という性質を持っているため、0埋めするようにします。

SELECT LPAD(HEX(49151), 6, "0");
-- 結果: 00BFFF

これで元の16進数カラーコードとunsigned integerの相互変換ができるようになりました。

10進数カラー→RGBへの変換

ここからが本題です。
まず、10進数を16進数に変換してから2桁ごとに10進数にするという2段階の手順が必要になります。

こんなイメージになります。これをSQLでやればRGBにまとめて変換できます。

  1. 49151->00BFFFに直す
  2. 2桁ごとに10進数に直す
    • 00 -> 0
    • BF -> 191
    • FF -> 255
SELECT
	CONV(SUBSTRING(LPAD(HEX(color_code_int), 6, "0"), 1, 2), 16, 10),
	CONV(SUBSTRING(LPAD(HEX(color_code_int), 6, "0"), 3, 2), 16, 10),
	CONV(SUBSTRING(LPAD(HEX(color_code_int), 6, "0"), 5, 2), 16, 10)
FROM color_code
WHERE id = 3;

-- 結果
|  R|  G|  B|
|---|---|---|
|  0|191|255|

16進数カラーコード(文字列)→RGBへの変換

こちらは先ほどよりシンプルで16進数を2桁ごとに10進数にするという、ひとつの手順だけで完了します。

SELECT
	CONV(SUBSTRING(color_code_string, 1, 2), 16, 10) AS R,
	CONV(SUBSTRING(color_code_string, 3, 2), 16, 10) AS G,
	CONV(SUBSTRING(color_code_string, 5, 2), 16, 10) AS B
FROM color_code
WHERE id = 3;

-- 結果
|  R|  G|  B|
|---|---|---|
|  0|191|255|

まとめ

10進数でも16進数の範囲内の文字列からでもRGBへの変換は可能でした。
16進数だと色がなんとなくわかるかもしれない点やメンテナンスがしやすい点がメリットのように感じます。
一方、10進数だと格納する際に変換する一手間が加わる点や何色かわかりづらいといったデメリットが目立ち、検証してみたけど10進数で扱うメリットが今のところ思いつかないです。(何かメリットがあればコメントお願いします🙇)

参考

https://dev.mysql.com/doc/refman/8.0/ja/hexadecimal-literals.html

Discussion