🚨

HSL色表現をフルカラーLEDに反映する方法

2022/12/28に公開約1,800字


色相を一周している

やりたいこと

人間的にはRGBで色を扱うのは直感的でないためHSLを使って最後にRGBに変換して反映したい。

https://ja.wikipedia.org/wiki/HLS色空間

を見ると変換アルゴリズムが書いてあるがこの類のものはだいたい先駆者がライブラリを用意してくれているはずなのでHSLをキーワードにして探してみる。と、ColorConverter というのがあったのでこれを使わせてもらう。

ところがライブラリが動かない

https://github.com/luisllamasbinaburo/Arduino-ColorConverter

README に Deprecated と書かれてあるしソースを見みても RGBConverter.h を読み込もうとしているのに実際のヘッダーファイルは ColorConverter.h だったりとちぐはぐしていて、いじってみたけどコンパイルできなかった。

なので必要な箇所だけ抜粋して使わせてもらうことにする。

hsl_to_rgb.ino
void hsl_to_rgb(double h, double s, double l, uint8_t& red, uint8_t& green, uint8_t& blue) {
  double r, g, b;
  if (s == 0) {
    r = g = b = l; // achromatic
  } else {
    auto q = l < 0.5 ? l * (1 + s) : l + s - l * s;
    auto p = 2 * l - q;
    r = hue_to_rgb(p, q, h + 1 / 3.0);
    g = hue_to_rgb(p, q, h);
    b = hue_to_rgb(p, q, h - 1 / 3.0);
  }
  red   = static_cast<uint8_t>(r * 255);
  green = static_cast<uint8_t>(g * 255);
  blue  = static_cast<uint8_t>(b * 255);
}

double hue_to_rgb(double p, double q, double t) {
  if (t < 0) t += 1;
  if (t > 1) t -= 1;
  if (t < 1 / 6.0) return p + (q - p) * 6 * t;
  if (t < 1 / 2.0) return q;
  if (t < 2 / 3.0) return p + (q - p) * (2 / 3.0 - t) * 6;
  return p;
}

コード

上の hsl_to_rgb.ino は、この sketch_main.ino と同じ場所に置いておく

sketch_main.ino
void setup() {
}

uint64_t count = 0;

void loop() {
  double h = fmod(1.0 / (60 * 4) * count, 1.0); // 1周4秒
  double s = 1.0;
  double l = 0.1;

  uint8_t r, g, b;
  hsl_to_rgb(h, s, l, r, g, b);

  analogWrite(6, r);
  analogWrite(5, g);
  analogWrite(3, b);

  count++;
  delay(1000 / 60);
}
  • 色相(H)
    • 一周 1.0
  • 彩度(S)
    • 0.5 なら色味が薄く淡い感じになる
    • 1.0 でいちばん色味が強くでる
  • 輝度(L)
    • 0.1 ぐらいでじゅうぶん明るい (CSS なら 0.1 はかなり暗いはずだけど)
    • 0.5 だと明るすぎて白に近い
  • 疑問
    • 輝度固定にしても色によって明るさが異なってるように感じる

Discussion

ログインするとコメントできます