LoginSignup
8
4

JavaScript / PHP:RGB HSV HSL 相互変換

Last updated at Posted at 2020-05-28

hsv2rgb

HSVからRGBに変換します。

hsv2rgb単独で動作します。

引数は h, s, v の順で渡します。
h = 0以上360未満の浮動小数点数
s = 0~1の浮動小数点数
v = 0~1の浮動小数点数

戻り値はRGBに変換した各値を連想配列で返します。
hex : #RRGGBB 形式の文字列
rgb : R, G, B 各値(0~255)の配列
r: Rの値(0~255の整数)
g: Gの値(0~255の整数)
b: Bの値(0~255の整数)

rgb2hsv

RGBからHSVに変換します。

rgb2hsv単独で動作します。

引数は r, g, b の順、または色コードで渡します。
r = 0~255の整数
g = 0~255の整数
b = 0~255の整数

色コードの場合は16進数6桁、または3桁で渡せます。
例えば3桁で18fと渡した場合は1188ffとして扱います。
11ffや221188ffなど6桁でも3桁でもない場合は、0011ffや1188ff等として扱います。
先頭に'#'は付けても付けなくても構いません。

戻り値はHSVに変換した各値を連想配列で返します。
h: Hの値(0以上360未満の浮動小数点数)
s: Sの値(0~1の浮動小数点数)
v: Vの値(0~1の浮動小数点数)

hsl2rgb

HSLからRGBに変換します。

hsl2rgbの他、sl2sv、hsv2rgbが必要です。

引数は h, s, l の順で渡します。
h = 0以上360未満の浮動小数点数
s = 0~1の浮動小数点数
l = 0~1の浮動小数点数

戻り値はhsv2rgbと同じです。

hsl2hsv

HSLからHSVに変換します。

hsl2hsvの他、sl2svが必要です。

引数はhsl2rgbと同じです。

戻り値はrgb2hsvと同じです。

rgb2hsl

RGBからHSLに変換します。

rgb2hslの他、rgb2hsv、sv2slが必要です。

引数はrgb2hsvと同じです。

戻り値はHSLに変換した各値を連想配列で返します。
h: Hの値(0以上360未満の浮動小数点数)
s: Sの値(0~1の浮動小数点数)
l: Lの値(0~1の浮動小数点数)

hsv2hsl

HSVからHSLに変換します。

hsv2hslの他、sv2slが必要です。

引数はhsv2rgbと同じです。

戻り値はrgb2hslと同じです。


スクリプト

JavaScript版

color_convert.js
/**
 *  hsv2rgb (h, s, v)
 */
function hsv2rgb(h, s, v) {
  // 引数処理
  h = (h < 0 ? h % 360 + 360 : h) % 360 / 60;
  s = s < 0 ? 0 : s > 1 ? 1 : s;
  v = v < 0 ? 0 : v > 1 ? 1 : v;

  // HSV to RGB 変換
  const c = [5, 3, 1].map(n =>
    Math.round((v - Math.max(0, Math.min(1, 2 - Math.abs(2 - (h + n) % 6))) * s * v) * 255));

  // 戻り値
  return {
    hex: `#${(c[0] << 16 | c[1] << 8 | c[2]).toString(16).padStart(6, '0')}`,
    rgb: c, r: c[0], g: c[1], b: c[2],
  };
}

/**
 *  rgb2hsv (r, g, b)
 *  rgb2hsv (colorcode)
 */
function rgb2hsv(r, g, b) {
  // 引数処理
  let tmp = [r, g, b];
  if (r !== void 0 && g === void 0) {
    const cc = parseInt(r.toString().replace(/[^\da-f]/ig, '').replace(/^(.)(.)(.)$/, "$1$1$2$2$3$3"), 16);
    tmp = [cc >> 16 & 0xff, cc >> 8 & 0xff, cc & 0xff];
  }
  else {
    for (let i in tmp) tmp[i] = Math.max(0, Math.min(255, Math.floor(tmp[i])));
  }
  [r, g, b] = tmp;

  // RGB to HSV 変換
  const
    v = Math.max(r, g, b), d = v - Math.min(r, g, b),
    s = v ? d / v : 0, a = [r, g, b, r, g], i = a.indexOf(v),
    h = s ? (((a[i + 1] - a[i + 2]) / d + i * 2 + 6) % 6) * 60 : 0;

  // 戻り値
  return {h, s, v: v / 255};
}

function sl2sv(s, l) {
  s = s < 0 ? 0 : s > 1 ? 1 : +s;
  l = l < 0 ? 0 : l > 1 ? 1 : +l;
  const
    n = l + s * Math.min(l, 1 - l),
    s_ = n ? (1 - l / n) * 2 : sl2sv(s, .5)[0];
  return [s_, n];
}

function sv2sl(s, v) {
  s = s < 0 ? 0 : s > 1 ? 1 : +s;
  v = v < 0 ? 0 : v > 1 ? 1 : +v;
  const
    n = v * (1 - s / 2),
    s_ = n ? (v - n) / Math.min(n, 1 - n) : sv2sl(s, .5)[0];
  return [s_, n];
}

/**
 *  hsl2rgb (h, s, l)
 */
function hsl2rgb(h, s, l) {
  const sv = sl2sv(s, l);
  return hsv2rgb(h, sv[0], sv[1]);
}

/**
 *  hsl2hsv (h, s, l)
 */
function hsl2hsv(h, s, l) {
  const sv = sl2sv(s, l);
  return {h, s: sv[0], v: sv[1]};
}

/**
 *  rgb2hsl (r, g, b)
 *  rgb2hsl (colorcode)
 */
function rgb2hsl(r, g, b) {
  const
    hsv = rgb2hsv(r, g, b),
    sl = sv2sl(hsv.s, hsv.v);
  return {h: hsv.h, s: sl[0], l: sl[1]};
}

/**
 *  hsv2hsl (h, s, v)
 */
function hsv2hsl(h, s, v) {
  const sl = sv2sl(s, v);
  return {h, s: sl[0], l: sl[1]};
}

example

const colorCode = '#4f8eac';
const hsv = rgb2hsv(colorCode);
console.log(`rgb2hsv('${colorCode}')`);
console.log(hsv);
console.log('h = ' + hsv.h);
console.log('s = ' + hsv.s);
console.log('v = ' + hsv.v);
/*
  rgb2hsv('#4f8eac')
  { h: 199.3548387096774, s: 0.5406976744186046, v: 0.6745098039215687 }
  h = 199.3548387096774
  s = 0.5406976744186046
  v = 0.6745098039215687
*/

const rgb = hsv2rgb(hsv.h, hsv.s, hsv.v);
console.log(`hsv2rgb(${hsv.h}, ${hsv.s}, ${hsv.v})`);
console.log(rgb);
console.log(rgb.rgb);
console.log('hex = ' + rgb.hex);
console.log('r = ' + rgb.r);
console.log('g = ' + rgb.g);
console.log('b = ' + rgb.b);
/*
  hsv2rgb(199.3548387096774, 0.5406976744186046, 0.6745098039215687)
  { hex: '#4f8eac', rgb: [ 79, 142, 172 ], r: 79, g: 142, b: 172 }
  [ 79, 142, 172 ]
  hex = #4f8eac
  r = 79
  g = 142
  b = 172
*/

console.log(rgb2hsl(255, 128, 64));
  // { h: 20.104712041884838, s: 1, l: 0.6254901960784314 }
console.log(hsl2rgb(20.104712041884838, 1, 0.6254901960784314));
  // { hex: '#ff8040', rgb: [ 255, 128, 64 ], r: 255, g: 128, b: 64 }
console.log(hsv2hsl(123, 0.75, 0.5));
  // { h: 123, s: 0.6, l: 0.3125 }
console.log(hsl2hsv(123, 0.6, 0.3125));
  // { h: 123, s: 0.75, v: 0.5 }

JavaScript版を使用した相互変換デモ


PHP版

color_convert.php
<?php
/**
 *  hsv2rgb (h, s, v)
 */
function hsv2rgb($h, $s, $v) {
  // 引数処理
  $h = ($h < 0 ? 360 + fmod($h, 360) : fmod($h, 360)) / 60;
  $s = max(0, min(1, $s));
  $v = max(0, min(1, $v));

  // HSV to RGB 変換
  foreach([5, 3, 1] as $k => $val) {
    $c[$k] = round(($v - max(0, min(1, 2 - abs(2 - fmod($h + $val, 6)))) * $s * $v) * 255);
  }

  // 戻り値
  return [
    'hex' => sprintf('#%02x%02x%02x', $c[0], $c[1], $c[2]),
    'rgb' => $c,
    'r' => $c[0],
    'g' => $c[1],
    'b' => $c[2],
  ];
}

/**
 *  rgb2hsv (r, g, b)
 *  rgb2hsv (colorcode)
 */
function rgb2hsv($r, $g = null, $b = null) {
  // 引数処理
  $tmp = [$r, $g, $b];
  if($r !== null && $g === null) {
    $cc = hexdec(preg_replace('/^(.)(.)(.)$/', "$1$1$2$2$3$3", preg_replace('/[^\da-f]/i', '' , $r)));
    $tmp = [$cc >> 16 & 0xff, $cc >> 8 & 0xff, $cc & 0xff];
  }
  else {
    foreach($tmp as $k => $v) $tmp[$k] = max(0, min(255, (int)$v));
  }
  [$r, $g, $b] = $tmp;

  // RGB to HSV 変換
  $v = max($r, $g, $b);
  $d = $v - min($r, $g, $b);
  $s = $v ? $d / $v : 0;
  $i = array_search($v, $a = [$r, $g, $b, $r, $g]);
  $h = $s ? fmod(($a[$i + 1] - $a[$i + 2]) / $d + $i * 2 + 6, 6) * 60 : 0;

  // 戻り値
  return [
    'h' => $h,
    's' => $s,
    'v' => $v / 255,
  ];
}

function sl2sv($s, $l) {
  $s = max(0, min(1, $s));
  $l = max(0, min(1, $l));
  $n = $l + $s * min($l, 1 - $l);
  $s_ = $n ? (1 - $l / $n) * 2 : sl2sv($s, .5)[0];
  return [$s_, $n];
}

function sv2sl($s, $v) {
  $s = max(0, min(1, $s));
  $v = max(0, min(1, $v));
  $n = $v * (1 - $s / 2);
  $s_ = $n ? ($v - $n) / min($n, 1 - $n) : sv2sl($s, .5)[0];
  return [$s_, $n];
}

/**
 *  hsl2rgb (h, s, l)
 */
function hsl2rgb($h, $s, $l) {
  $sv = sl2sv($s, $l);
  return hsv2rgb($h, $sv[0], $sv[1]);
}

/**
 *  hsl2hsv (h, s, l)
 */
function hsl2hsv($h, $s, $l) {
  $sv = sl2sv($s, $l);
  return ['h' => $h, 's' => $sv[0], 'v' => $sv[1]];
}

/**
 *  rgb2hsl (r, g, b)
 *  rgb2hsl (colorcode)
 */
function rgb2hsl($r, $g, $b) {
  $hsv = rgb2hsv($r, $g, $b);
  $sl = sv2sl($hsv['s'], $hsv['v']);
  return ['h' => $hsv['h'], 's' => $sl[0], 'l' => $sl[1]];
}

/**
 *  hsv2hsl (h, s, v)
 */
function hsv2hsl($h, $s, $v) {
  $sl = sv2sl($s, $v);
  return ['h' => $h, 's' => $sl[0], 'l' => $sl[1]];
}

example

$colorCode = '#4f8eac';

print "rgb2hsv('{$colorCode}')\n";
$hsv = rgb2hsv($colorCode);
print_r($hsv);
/*
  rgb2hsv('#4f8eac')
  Array
  (
      [h] => 199.35483870968
      [s] => 0.5406976744186
      [v] => 0.67450980392157
  )
*/

print "hsv2rgb({$hsv['h']}, {$hsv['s']}, {$hsv['v']})\n";
$rgb = hsv2rgb($hsv['h'], $hsv['s'], $hsv['v']);
print_r($rgb);
/*
  hsv2rgb(199.35483870968, 0.5406976744186, 0.67450980392157)
  Array
  (
      [hex] => #4f8eac
      [rgb] => Array
          (
              [0] => 79
              [1] => 142
              [2] => 172
          )

      [r] => 79
      [g] => 142
      [b] => 172
  )
*/

print_r(rgb2hsl(255, 128, 64));
/*
  Array
  (
      [h] => 20.104712041885
      [s] => 1
      [l] => 0.62549019607843
  )
*/

print_r(hsl2rgb(20.104712041885, 1, 0.62549019607843));
/*
  Array
  (
      [hex] => #ff8040
      [rgb] => Array
          (
              [0] => 255
              [1] => 128
              [2] => 64
          )

      [r] => 255
      [g] => 128
      [b] => 64
  )
*/

print_r(hsv2hsl(123, 0.75, 0.5));
/*
  Array
  (
      [h] => 123
      [s] => 0.6
      [l] => 0.3125
  )
*/

print_r(hsl2hsv(123, 0.6, 0.3125));
/*
  Array
  (
      [h] => 123
      [s] => 0.75
      [v] => 0.5
  )
*/

関連記事 JavaScript input要素に対して使用可能なカラーピッカーUIを作成

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4