How to convert LIFX HSBK to HEX/RGB (e.g. #00FF00)

I’m developing my own web-based UI to control our Lifx lights. The LIFX API’s give us the current color as HSBK, but to represent that on a webpage I need to convert it to hex (e.g. #00FF00).

Can anyone point me in the right direction?

Thanks!

Head over to https://www.w3schools.com/csSref/css_colors_legal.asp and scroll down to the section for HSL colours. No need to convert HSL to HEX.

2 Likes

Wow! I can’t believe I hadn’t come across that! Thanks so much!

Follow up question:

When my bulb is set to deep green, the HTTP API returns:

HUE: 86
Saturation: 1.0
Brightness: 1.0

However, when I try to show that in css as

hsl(86, 100%, 100%) the resulting color is white! But if I change the L to 50%, it comes through as green.

This leads me to believe there’s a difference between LIFX “Brightness” versus CSS “Lightness”. i.e. LIFX 1.0 Brightness is not the same thing as CSS 100% “Lightness”.

Can anyone help shed light on this?

Thanks!

No worries.

With regards to the lightness, I figured that 0-50% results in brightness of the colour and 50-100% results in adding white to the colour. It could be deliberate in that as you can control the LIFX light the same way via the native iOS and Android App.

1 Like

I gathered that “Brightness” is known as “Value” in other circles since the LIFX support on HSBK links you directly to this page, which explicitly calls out Brightness, Lightness, and Value. In short, HSB = HSV, and NOT HSL. In CSS, is there an HSV function instead of HSL?

-Brian

1 Like

You nailed it Bryan (and helped me out)!

When I was using HSL conversion formulas, it only worked when saturations were high. Switching to HSV is much more accurate.

e.g. with HSL a very low saturation would convert to dark-ish gray. But with HSV, it converts properly to near-white.

Matt… What formula are you using to convert HSV to RGB? I’m using the formula listed here https://gist.github.com/mjackson/5311256 but the color still isn’t quite accurate

1 Like
function hsv_to_rgb($iH, $iS, $iV) {

if($iH < 0)   $iH = 0;   // Hue:
if($iH > 360) $iH = 360; //   0-360
if($iS < 0)   $iS = 0;   // Saturation:
if($iS > 100) $iS = 100; //   0-100
if($iV < 0)   $iV = 0;   // Lightness:
if($iV > 100) $iV = 100; //   0-100

$dS = $iS/100.0; // Saturation: 0.0-1.0
$dV = $iV/100.0; // Lightness:  0.0-1.0
$dC = $dV*$dS;   // Chroma:     0.0-1.0
$dH = $iH/60.0;  // H-Prime:    0.0-6.0
$dT = $dH;       // Temp variable

while($dT >= 2.0) $dT -= 2.0; // php modulus does not work with float
$dX = $dC*(1-abs($dT-1));     // as used in the Wikipedia link

switch(floor($dH)) {
    case 0:
        $dR = $dC; $dG = $dX; $dB = 0.0; break;
    case 1:
        $dR = $dX; $dG = $dC; $dB = 0.0; break;
    case 2:
        $dR = 0.0; $dG = $dC; $dB = $dX; break;
    case 3:
        $dR = 0.0; $dG = $dX; $dB = $dC; break;
    case 4:
        $dR = $dX; $dG = 0.0; $dB = $dC; break;
    case 5:
        $dR = $dC; $dG = 0.0; $dB = $dX; break;
    default:
        $dR = 0.0; $dG = 0.0; $dB = 0.0; break;
}

$dM  = $dV - $dC;
$dR += $dM; $dG += $dM; $dB += $dM;
$dR *= 255; $dG *= 255; $dB *= 255;

# This would return RGB
#return round($dR).",".round($dG).",".round($dB);

# Instead we'll return html HEX
$color = dechex( ($dR << 16) + ($dG << 8) + $dB );
return '#' . str_repeat('0', 6 - strlen($color)) . $color;

}

$hex = hsv_to_rgb($color[‘h’], $color[‘s’]*100, $color[‘b’]*100);

For anyone needing, I converted the function from PHP to javascript…

function hsv_to_rgb($iH, $iS, $iV) {

  if($iH < 0)   $iH = 0;   // Hue:
  if($iH > 360) $iH = 360; //   0-360
  if($iS < 0)   $iS = 0;   // Saturation:
  if($iS > 100) $iS = 100; //   0-100
  if($iV < 0)   $iV = 0;   // Lightness:
  if($iV > 100) $iV = 100; //   0-100

  let $dS = $iS/100.0; // Saturation: 0.0-1.0
  let $dV = $iV/100.0; // Lightness:  0.0-1.0
  let $dC = $dV*$dS;   // Chroma:     0.0-1.0
  let $dH = $iH/60.0;  // H-Prime:    0.0-6.0
  let $dT = $dH;       // Temp variable

  while($dT >= 2.0) $dT -= 2.0;
  let $dX = $dC*(1-Math.abs($dT-1));

    let $dR, $dG, $dB;

  switch(Math.floor($dH)) {
      case 0:
          $dR = $dC; $dG = $dX; $dB = 0.0; break;
      case 1:
          $dR = $dX; $dG = $dC; $dB = 0.0; break;
      case 2:
          $dR = 0.0; $dG = $dC; $dB = $dX; break;
      case 3:
          $dR = 0.0; $dG = $dX; $dB = $dC; break;
      case 4:
          $dR = $dX; $dG = 0.0; $dB = $dC; break;
      case 5:
          $dR = $dC; $dG = 0.0; $dB = $dX; break;
      default:
          $dR = 0.0; $dG = 0.0; $dB = 0.0; break;
  }

  let $dM  = $dV - $dC;
  $dR += $dM; $dG += $dM; $dB += $dM;
  $dR *= 255; $dG *= 255; $dB *= 255;

  // This would return RGB
  return Math.round($dR)+","+Math.round($dG)+","+Math.round($dB);

  // This would return html HEX
  //$color = dechex( ($dR << 16) + ($dG << 8) + $dB );
  //return '#' . str_repeat('0', 6 - strlen($color)) . $color;

}

Thanks @bucedup! I converted the function from Javascript to Java. :smile:

    private static String hsvToRgb(int iH, int iS, int iV) {

        if(iH < 0)   iH = 0;   // Hue:
        if(iH > 360) iH = 360; //   0-360
        if(iS < 0)   iS = 0;   // Saturation:
        if(iS > 100) iS = 100; //   0-100
        if(iV < 0)   iV = 0;   // Lightness:
        if(iV > 100) iV = 100; //   0-100

        double dS = iS/100.0; // Saturation: 0.0-1.0
        double dV = iV/100.0; // Lightness:  0.0-1.0
        double dC = dV*dS;    // Chroma:     0.0-1.0
        double dH = iH/60.0;  // H-Prime:    0.0-6.0
        double dT = dH;       // Temp variable

        while(dT >= 2.0) dT -= 2.0;
        double dX = dC*(1-Math.abs(dT-1));

        double dR, dG, dB;

        double dHf = Math.floor(dH);
        if (dHf == 0) { dR = dC; dG = dX; dB = 0.0; }
        else if (dHf == 1) { dR = dX; dG = dC; dB = 0.0; }
        else if (dHf == 2) { dR = 0.0; dG = dC; dB = dX; }
        else if (dHf == 3) { dR = 0.0; dG = dX; dB = dC; }
        else if (dHf == 4) { dR = dX; dG = 0.0; dB = dC; }
        else if (dHf == 5) { dR = dC; dG = 0.0; dB = dX; }
        else { dR = 0.0; dG = 0.0; dB = 0.0; }

        double dM  = dV - dC;
        dR += dM; dG += dM; dB += dM;
        dR *= 255; dG *= 255; dB *= 255;

        // This would return RGB
        //return Math.round(dR)+","+Math.round(dG)+","+Math.round(dB);

        // This would return html HEX
        String color = Long.toHexString(((int) Math.round(dR) << 16) + ((int) Math.round(dG) << 8) + (int) Math.round(dB));
        return "#" + String.join("", Collections.nCopies(6 - color.length(), "0")) + color;

    }