HSL to RGB color conversion

后端 未结 21 2621
忘了有多久
忘了有多久 2020-11-22 01:59

I am looking for a JavaScript / PHP algorithm to convert between HSL color to RGB.

It seems to me that HSL is not very widely used so I am not having much luck search

相关标签:
21条回答
  • 2020-11-22 02:21

    I got this from Brandon Mathis' HSL Picker source code.

    It was originally written in CoffeeScript. I converted it to JavaScript using an online converter, and took out the mechanism to verify the user input was a valid RGB value. This answer worked for my usecase, as the most up-voted answer on this post I found to not produce a valid HSL value.

    Note that it returns an hsla value, with a representing opacity/transparency. 0 is completely transparent, and 1 fully opaque.

    function rgbToHsl(rgb) {
      var a, add, b, diff, g, h, hue, l, lum, max, min, r, s, sat;
      r = parseFloat(rgb[0]) / 255;
      g = parseFloat(rgb[1]) / 255;
      b = parseFloat(rgb[2]) / 255;
      max = Math.max(r, g, b);
      min = Math.min(r, g, b);
      diff = max - min;
      add = max + min;
      hue = min === max ? 0 : r === max ? ((60 * (g - b) / diff) + 360) % 360 : g === max ? (60 * (b - r) / diff) + 120 : (60 * (r - g) / diff) + 240;
      lum = 0.5 * add;
      sat = lum === 0 ? 0 : lum === 1 ? 1 : lum <= 0.5 ? diff / add : diff / (2 - add);
      h = Math.round(hue);
      s = Math.round(sat * 100);
      l = Math.round(lum * 100);
      a = parseFloat(rgb[3]) || 1;
      return [h, s, l, a];
    }
    
    0 讨论(0)
  • 2020-11-22 02:21

    An hsl|a color value, set in javascript, will be instantly converted to rgb|a All you need to do then is access the computed style value

    document.body.style.color = 'hsla(44, 100%, 50%, 0.8)';
    
    console.log(window.getComputedStyle(document.body).color);
    
    // displays: rgba(255, 187, 0, 0.8)
    

    Technically, I guess, this isn't even any lines of code - it's just done automatically. So, depending on your environment, you might be able to get away with just this. Not that there aren't a lot of very thoughtful responses here. I don't know what your goal is.

    Now, what if you want to convert from rbg|a to hsl|a?

    0 讨论(0)
  • 2020-11-22 02:21

    Shortest but precise - JS

    Use this JS code (more: rgb2hsl, hsv2rgb rgb2hsv and hsl2hsv) - php here

    // input: h in [0,360] and s,v in [0,1] - output: r,g,b in [0,1]
    function hsl2rgb(h,s,l) 
    {
      let a=s*Math.min(l,1-l);
      let f= (n,k=(n+h/30)%12) => l - a*Math.max(Math.min(k-3,9-k,1),-1);                 
      return [f(0),f(8),f(4)];
    }   
    

    // oneliner version
    let hsl2rgb = (h,s,l, a=s*Math.min(l,1-l), f= (n,k=(n+h/30)%12) => l - a*Math.max(Math.min(k-3,9-k,1),-1)) => [f(0),f(8),f(4)];
    
    // r,g,b are in [0-1], result e.g. #0812fa.
    let rgb2hex = (r,g,b) => "#" + [r,g,b].map(x=>Math.round(x*255).toString(16).padStart(2,0) ).join('');
    
    
    console.log(`hsl: (30,0.2,0.3) --> rgb: (${hsl2rgb(30,0.2,0.3)}) --> hex: ${rgb2hex(...hsl2rgb(30,0.2,0.3))}`);
    
    
    
    // ---------------
    // UX
    // ---------------
    
    rgb= [0,0,0];
    hs= [0,0,0];
    
    let $ = x => document.querySelector(x);
    
    function changeRGB(i,e) {
      rgb[i]=e.target.value/255;
      hs = rgb2hsl(...rgb);
      refresh();
    }
    
    function changeHS(i,e) {
      hs[i]=e.target.value/(i?255:1);
      rgb= hsl2rgb(...hs);
      refresh();
    }
    
    function refresh() {
      rr = rgb.map(x=>x*255|0).join(', ')
      hh = rgb2hex(...rgb);
      tr = `RGB: ${rr}`
      th = `HSL: ${hs.map((x,i)=>i? (x*100).toFixed(2)+'%':x|0).join(', ')}`
      thh= `HEX: ${hh}`
      $('.box').style.backgroundColor=`rgb(${rr})`;  
      $('.infoRGB').innerHTML=`${tr}`;  
      $('.infoHS').innerHTML =`${th}\n${thh}`;  
      
      $('#r').value=rgb[0]*255;
      $('#g').value=rgb[1]*255;
      $('#b').value=rgb[2]*255;
      
      $('#h').value=hs[0];
      $('#s').value=hs[1]*255;
      $('#l').value=hs[2]*255;  
    }
    
    function rgb2hsl(r,g,b) {
      let a=Math.max(r,g,b), n=a-Math.min(r,g,b), f=(1-Math.abs(a+a-n-1)); 
      let h= n && ((a==r) ? (g-b)/n : ((a==g) ? 2+(b-r)/n : 4+(r-g)/n)); 
      return [60*(h<0?h+6:h), f ? n/f : 0, (a+a-n)/2];
    }
    
    refresh();
    .box {
      width: 50px;
      height: 50px;
      margin: 20px;
    }
    
    body {
        display: flex;
    }
    <div>
    <input id="r" type="range" min="0" max="255" oninput="changeRGB(0,event)">R<br>
    <input id="g" type="range" min="0" max="255" oninput="changeRGB(1,event)">G<br>
    <input id="b" type="range" min="0" max="255" oninput="changeRGB(2,event)">B<br>
    <pre class="infoRGB"></pre>
    </div> 
    
    <div>
    <div class="box hsl"></div>
    
    </div>
    
    <div>
    <input id="h" type="range" min="0" max="360" oninput="changeHS(0,event)">H<br>
    <input id="s" type="range" min="0" max="255" oninput="changeHS(1,event)">S<br>
    <input id="l" type="range" min="0" max="255" oninput="changeHS(2,event)">L<br>
    <pre class="infoHS"></pre><br>
    </div>

    Here is formula which I discover and precisely describe in wiki + error analysis,

    0 讨论(0)
  • 2020-11-22 02:22

    Here's a fast, super-simple, branchless version in GLSL:

    vec3 hsl2rgb( vec3 c ) {
        vec3 rgb = clamp(abs(mod(c.x*6.0 + vec3(0.0, 4.0, 2.0), 6.0)-3.0)-1.0, 0.0, 1.0);
        return c.z + c.y * (rgb-0.5)*(1.0-abs(2.0*c.z-1.0));
    }
    

    Doesn't get much shorter than that ~


    Link to the original proof-of-concept: https://www.shadertoy.com/view/XljGzV

    (Disclaimer: not my code!)

    0 讨论(0)
  • 2020-11-22 02:25

    Garry Tan posted a Javascript solution on his blog (which he attributes to a now defunct mjijackson.com, but is archived here and the original author has a gist - thanks to user2441511).

    The code is re-posted below:

    HSL to RGB:

    /**
     * Converts an HSL color value to RGB. Conversion formula
     * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
     * Assumes h, s, and l are contained in the set [0, 1] and
     * returns r, g, and b in the set [0, 255].
     *
     * @param   {number}  h       The hue
     * @param   {number}  s       The saturation
     * @param   {number}  l       The lightness
     * @return  {Array}           The RGB representation
     */
    function hslToRgb(h, s, l){
        var r, g, b;
    
        if(s == 0){
            r = g = b = l; // achromatic
        }else{
            var hue2rgb = function hue2rgb(p, q, t){
                if(t < 0) t += 1;
                if(t > 1) t -= 1;
                if(t < 1/6) return p + (q - p) * 6 * t;
                if(t < 1/2) return q;
                if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
                return p;
            }
    
            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
            var p = 2 * l - q;
            r = hue2rgb(p, q, h + 1/3);
            g = hue2rgb(p, q, h);
            b = hue2rgb(p, q, h - 1/3);
        }
    
        return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
    }
    

    RGB to HSL:

    /**
     * Converts an RGB color value to HSL. Conversion formula
     * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
     * Assumes r, g, and b are contained in the set [0, 255] and
     * returns h, s, and l in the set [0, 1].
     *
     * @param   {number}  r       The red color value
     * @param   {number}  g       The green color value
     * @param   {number}  b       The blue color value
     * @return  {Array}           The HSL representation
     */
    function rgbToHsl(r, g, b){
        r /= 255, g /= 255, b /= 255;
        var max = Math.max(r, g, b), min = Math.min(r, g, b);
        var h, s, l = (max + min) / 2;
    
        if(max == min){
            h = s = 0; // achromatic
        }else{
            var d = max - min;
            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
            switch(max){
                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                case g: h = (b - r) / d + 2; break;
                case b: h = (r - g) / d + 4; break;
            }
            h /= 6;
        }
    
        return [h, s, l];
    }
    
    0 讨论(0)
  • 2020-11-22 02:25

    PHP implementation of @Mohsen's code (including Test!)

    Sorry to re-post this. But I really haven't seen any other implementation that gives the quality I needed.

    /**
     * Converts an HSL color value to RGB. Conversion formula
     * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
     * Assumes h, s, and l are contained in the set [0, 1] and
     * returns r, g, and b in the set [0, 255].
     *
     * @param   {number}  h       The hue
     * @param   {number}  s       The saturation
     * @param   {number}  l       The lightness
     * @return  {Array}           The RGB representation
     */
      
    function hue2rgb($p, $q, $t){
                if($t < 0) $t += 1;
                if($t > 1) $t -= 1;
                if($t < 1/6) return $p + ($q - $p) * 6 * $t;
                if($t < 1/2) return $q;
                if($t < 2/3) return $p + ($q - $p) * (2/3 - $t) * 6;
                return $p;
            }
    function hslToRgb($h, $s, $l){
        if($s == 0){
            $r = $l;
            $g = $l;
            $b = $l; // achromatic
        }else{
            $q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s;
            $p = 2 * $l - $q;
            $r = hue2rgb($p, $q, $h + 1/3);
            $g = hue2rgb($p, $q, $h);
            $b = hue2rgb($p, $q, $h - 1/3);
        }
    
        return array(round($r * 255), round($g * 255), round($b * 255));
    }
    
    /* Uncomment to test * /
    for ($i=0;$i<360;$i++) {
      $rgb=hslToRgb($i/360, 1, .9);
      echo '<div style="background-color:rgb(' .$rgb[0] . ', ' . $rgb[1] . ', ' . $rgb[2] . ');padding:2px;"></div>';
    }
    /* End Test */
    
    0 讨论(0)
提交回复
热议问题