HSL to RGB color conversion

后端 未结 21 2719
忘了有多久
忘了有多久 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:26

    C# Code from Mohsen's answer.

    Here is the code from Mohsen's answer in C# if anyone else wants it. Note: Color is a custom class and Vector4 is from OpenTK. Both are easy to replace with something else of your choosing.

    Hsl To Rgba

    /// <summary>
    /// Converts an HSL color value to RGB.
    /// Input: Vector4 ( X: [0.0, 1.0], Y: [0.0, 1.0], Z: [0.0, 1.0], W: [0.0, 1.0] )
    /// Output: Color ( R: [0, 255], G: [0, 255], B: [0, 255], A: [0, 255] )
    /// </summary>
    /// <param name="hsl">Vector4 defining X = h, Y = s, Z = l, W = a. Ranges [0, 1.0]</param>
    /// <returns>RGBA Color. Ranges [0, 255]</returns>
    public static Color HslToRgba(Vector4 hsl)
    {
        float r, g, b;
    
        if (hsl.Y == 0.0f)
            r = g = b = hsl.Z;
    
        else
        {
            var q = hsl.Z < 0.5f ? hsl.Z * (1.0f + hsl.Y) : hsl.Z + hsl.Y - hsl.Z * hsl.Y;
            var p = 2.0f * hsl.Z - q;
            r = HueToRgb(p, q, hsl.X + 1.0f / 3.0f);
            g = HueToRgb(p, q, hsl.X);
            b = HueToRgb(p, q, hsl.X - 1.0f / 3.0f);
        }
    
        return new Color((int)(r * 255), (int)(g * 255), (int)(b * 255), (int)(hsl.W * 255));
    }
    
    // Helper for HslToRgba
    private static float HueToRgb(float p, float q, float t)
    {
        if (t < 0.0f) t += 1.0f;
        if (t > 1.0f) t -= 1.0f;
        if (t < 1.0f / 6.0f) return p + (q - p) * 6.0f * t;
        if (t < 1.0f / 2.0f) return q;
        if (t < 2.0f / 3.0f) return p + (q - p) * (2.0f / 3.0f - t) * 6.0f;
        return p;
    }
    

    Rgba To Hsl

    /// <summary>
    /// Converts an RGB color value to HSL.
    /// Input: Color ( R: [0, 255], G: [0, 255], B: [0, 255], A: [0, 255] )
    /// Output: Vector4 ( X: [0.0, 1.0], Y: [0.0, 1.0], Z: [0.0, 1.0], W: [0.0, 1.0] )
    /// </summary>
    /// <param name="rgba"></param>
    /// <returns></returns>
    public static Vector4 RgbaToHsl(Color rgba)
    {
        float r = rgba.R / 255.0f;
        float g = rgba.G / 255.0f;
        float b = rgba.B / 255.0f;
    
        float max = (r > g && r > b) ? r : (g > b) ? g : b;
        float min = (r < g && r < b) ? r : (g < b) ? g : b;
    
        float h, s, l;
        h = s = l = (max + min) / 2.0f;
    
        if (max == min)
            h = s = 0.0f;
    
        else
        {
            float d = max - min;
            s = (l > 0.5f) ? d / (2.0f - max - min) : d / (max + min);
    
            if (r > g && r > b)
                h = (g - b) / d + (g < b ? 6.0f : 0.0f);
    
            else if (g > b)
                h = (b - r) / d + 2.0f;
    
            else
                h = (r - g) / d + 4.0f;
    
            h /= 6.0f;
        }
    
        return new Vector4(h, s, l, rgba.A / 255.0f);
    }
    
    0 讨论(0)
  • 2020-11-22 02:27

    Java implementation of Mohsen's code

    Note that all integer are declared as float (i.e 1f) and must be float, else you will optain grey colors.

    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 h       The hue
     * @param s       The saturation
     * @param l       The lightness
     * @return int array, the RGB representation
     */
    public static int[] hslToRgb(float h, float s, float l){
        float r, g, b;
    
        if (s == 0f) {
            r = g = b = l; // achromatic
        } else {
            float q = l < 0.5f ? l * (1 + s) : l + s - l * s;
            float p = 2 * l - q;
            r = hueToRgb(p, q, h + 1f/3f);
            g = hueToRgb(p, q, h);
            b = hueToRgb(p, q, h - 1f/3f);
        }
        int[] rgb = {to255(r), to255(g), to255(b)};
        return rgb;
    }
    public static int to255(float v) { return (int)Math.min(255,256*v); }
    
    /** Helper method that converts hue to rgb */
    public static float hueToRgb(float p, float q, float t) {
        if (t < 0f)
            t += 1f;
        if (t > 1f)
            t -= 1f;
        if (t < 1f/6f)
            return p + (q - p) * 6f * t;
        if (t < 1f/2f)
            return q;
        if (t < 2f/3f)
            return p + (q - p) * (2f/3f - t) * 6f;
        return p;
    }
    

    RGB to HSL

    /**
     * Converts an RGB color value to HSL. Conversion formula
     * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
     * Assumes pR, pG, and bpBare contained in the set [0, 255] and
     * returns h, s, and l in the set [0, 1].
     *
     * @param pR       The red color value
     * @param pG       The green color value
     * @param pB       The blue color value
     * @return float array, the HSL representation
     */
    public static float[] rgbToHsl(int pR, int pG, int pB) {
        float r = pR / 255f;
        float g = pG / 255f;
        float b = pB / 255f;
    
        float max = (r > g && r > b) ? r : (g > b) ? g : b;
        float min = (r < g && r < b) ? r : (g < b) ? g : b;
    
        float h, s, l;
        l = (max + min) / 2.0f;
    
        if (max == min) {
            h = s = 0.0f;
        } else {
            float d = max - min;
            s = (l > 0.5f) ? d / (2.0f - max - min) : d / (max + min);
    
            if (r > g && r > b)
                h = (g - b) / d + (g < b ? 6.0f : 0.0f);
    
            else if (g > b)
                h = (b - r) / d + 2.0f;
    
            else
                h = (r - g) / d + 4.0f;
    
            h /= 6.0f;
        }
    
        float[] hsl = {h, s, l};
        return hsl;
    }
    
    0 讨论(0)
  • 2020-11-22 02:27

    PHP - shortest but precise

    Here I rewrite my JS answer (math details are there) to PHP - you can run it here

    function hsl2rgb($h,$s,$l) 
    {
      $a = $s * min($l, 1-$l);
      $k = function($n,$h) { return ($n+$h/30)%12;};
      $f = function($n) use ($h,$s,$l,$a,$k) { 
          return $l - $a * max( min($k($n,$h)-3, 9-$k($n,$h), 1),-1);
      };
      return [ $f(0), $f(8), $f(4) ];
    }   
    
    0 讨论(0)
  • 2020-11-22 02:29

    Unity3D C# Code from Mohsen's answer.

    Here is the code from Mohsen's answer in C# targeted specifically for Unity3D. It was adapted from the C# answer given by Alec Thilenius above.

    using UnityEngine;
    using System.Collections;
    
    public class ColorTools {
    
        /// <summary>
        /// Converts an HSL color value to RGB.
        /// Input: Vector4 ( X: [0.0, 1.0], Y: [0.0, 1.0], Z: [0.0, 1.0], W: [0.0, 1.0] )**strong text**
        /// Output: Color ( R: [0.0, 1.0], G: [0.0, 1.0], B: [0.0, 1.0], A: [0.0, 1.0] )
        /// </summary>
        /// <param name="hsl">Vector4 defining X = h, Y = s, Z = l, W = a. Ranges [0, 1.0]</param>
        /// <returns>RGBA Color. Ranges [0.0, 1.0]</returns>
        public static Color HslToRgba(Vector4 hsl)
        {
            float r, g, b;
    
            if (hsl.y == 0.0f)
                r = g = b = hsl.z;
            else
            {
                var q = hsl.z < 0.5f ? hsl.z * (1.0f + hsl.y) : hsl.z + hsl.y - hsl.z * hsl.y;
                var p = 2.0f * hsl.z - q;
                r = HueToRgb(p, q, hsl.x + 1.0f / 3.0f);
                g = HueToRgb(p, q, hsl.x);
                b = HueToRgb(p, q, hsl.x - 1.0f / 3.0f);
            }
    
            return new Color(r, g, b, hsl.w);
        }
    
        // Helper for HslToRgba
        private static float HueToRgb(float p, float q, float t)
        {
            if (t < 0.0f) t += 1.0f;
            if (t > 1.0f) t -= 1.0f;
            if (t < 1.0f / 6.0f) return p + (q - p) * 6.0f * t;
            if (t < 1.0f / 2.0f) return q;
            if (t < 2.0f / 3.0f) return p + (q - p) * (2.0f / 3.0f - t) * 6.0f;
            return p;
        }
    
        /// <summary>
        /// Converts an RGB color value to HSL.
        /// Input: Color ( R: [0.0, 1.0], G: [0.0, 1.0], B: [0.0, 1.0], A: [0.0, 1.0] )
        /// Output: Vector4 ( X: [0.0, 1.0], Y: [0.0, 1.0], Z: [0.0, 1.0], W: [0.0, 1.0] )
        /// </summary>
        /// <param name="rgba"></param>
        /// <returns></returns>
        public static Vector4 RgbaToHsl(Color rgba)
        {
    
            float max = (rgba.r > rgba.g && rgba.r > rgba.b) ? rgba.r : 
                (rgba.g > rgba.b) ? rgba.g : rgba.b;
            float min = (rgba.r < rgba.g && rgba.r < rgba.b) ? rgba.r : 
                (rgba.g < rgba.b) ? rgba.g : rgba.b;
    
            float h, s, l;
            h = s = l = (max + min) / 2.0f;
    
            if (max == min)
                h = s = 0.0f;
            else
            {
                float d = max - min;
                s = (l > 0.5f) ? d / (2.0f - max - min) : d / (max + min);
    
                if (rgba.r > rgba.g && rgba.r > rgba.b)
                    h = (rgba.g - rgba.b) / d + (rgba.g < rgba.b ? 6.0f : 0.0f);
    
                else if (rgba.g > rgba.b)
                    h = (rgba.b - rgba.r) / d + 2.0f;
    
                else
                    h = (rgba.r - rgba.g) / d + 4.0f;
    
                h /= 6.0f;
            }
    
            return new Vector4(h, s, l, rgba.a);
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 02:30

    For all who said that Garry Tan solution converting incorrect from RGB to HSL and back. It because he left out fraction part of number in his code. I corrected his code (javascript). Sorry for link on russian languadge, but on english absent - HSL-wiki

    function toHsl(r, g, b)
    {
        r /= 255.0;
        g /= 255.0;
        b /= 255.0;
        var max = Math.max(r, g, b);
        var min = Math.min(r, g, b);
        var h, s, l = (max + min) / 2.0;
    
        if(max == min)
        {
            h = s = 0; 
        }
        else
        {
            var d = max - min;
            s = (l > 0.5 ? d / (2.0 - max - min) : d / (max + min));
    
            if(max == r && g >= b)
            {
                h = 1.0472 * (g - b) / d ;
            }
            else if(max == r && g < b)
            {
                h = 1.0472 * (g - b) / d + 6.2832;
            }
            else if(max == g)
            {
                h = 1.0472 * (b - r) / d + 2.0944;
            }
            else if(max == b)
            {
                h = 1.0472 * (r - g) / d + 4.1888;
            }
        }
        return {
            str: 'hsl(' + parseInt(h / 6.2832 * 360.0 + 0.5) + ',' + parseInt(s * 100.0 + 0.5) + '%,' + parseInt(l * 100.0 + 0.5) + '%)',
            obj: { h: parseInt(h / 6.2832 * 360.0 + 0.5), s: parseInt(s * 100.0 + 0.5), l: parseInt(l * 100.0 + 0.5) }
        };
    };
    
    0 讨论(0)
  • 2020-11-22 02:31

    The article for HSL and HSV on wikipedia contains some formulas. The calculations are a bit tricky, so it might be useful to take a look at existing implementations.

    0 讨论(0)
提交回复
热议问题