HSL - RGB renk dönüşümü [kapalı]


174

Ben HSL renk RGB dönüştürmek için bir JavaScript / PHP algoritması arıyorum.

Bana öyle geliyor ki HSL çok yaygın olarak kullanılmıyor, bu yüzden bir dönüştürücü aramak için fazla şansım yok.



1
Tarayıcı tarafında - d3.js bunun için iyi bir API'ya sahiptir: github.com/mbostock/d3/wiki/Colors
matanster

ödeme lütfen js Please.HEX_to_HSV('#ffeb3b')
Lex

4
Açık bir şekilde stackoverflow.com/help/on-topic adresinde bir 'konu' olan bir algoritma istemesine rağmen konu dışı olarak işaretlendi - ne veriyor?
LeeGee

2
Bu, bu sitede gördüğüm en kötü oylama yaklaşımı ve bu çok şey söylüyor! Yeniden açılan ilk oylama benim.
Theodore R. Smith

Yanıtlar:


300

Garry Tan , blogunda bir Javascript çözümü yayınladı (artık geçersiz bir mjijackson.com'a atfediyor, ancak burada arşivleniyor ve orijinal yazarın bir kullanıcısı var - user2441511 sayesinde).

Kod aşağıda yeniden gönderilmiştir:

HSL'den RGB'ye:

/**
 * 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'den HSL'ye:

/**
 * 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];
}

15
Yorumların bana değişkenlerin aralığını ve çıktı olarak ne bekleyeceğini anlatmasını seviyorum. Çok düzenli. Teşekkürler!
Gleno

9
Bunu bir proje için kullanmaya çalışıyorum, ancak sonuçlarım sadece gri tonlamalı olarak çıkıyor. Bu HSL <-> RGB'nin bir sınırlaması mıdır? Wikipedia makalesi, 3 kanalın tümüne yalnızca tek bir değerin ayarlandığını düşündürmektedir.
Bill

10
Kullanmanın Math.roundölçeğin düşük ve yüksek uçlarında (0 ve 255 değerleri) küçük yanlışlıklar getirdiğini belirtmek isterim . Aralığın uçlarında bulunmayan değerler, değerlerine ulaşmak için yukarı veya aşağı yuvarlanabilir, ancak değerler yalnızca 0 veya 255'e kadar yuvarlanabilir. Bu, 0 ve 255 ile eşleşen değer aralığının tam olarak olduğu anlamına gelir. diğer değerlerin yarısı. Bunu düzeltmek için, onun yerine bu formülü kullanın: min(floor(val*256),255). Bu haritalamayı neredeyse mükemmel hale getirir.
marcus erronius

13
Eğer gri tonlama değerleri alıyorsanız eğer Ayrıca, Çünkü kullanmak çizgilerin muhtemelen h + 1/3ve h - 1/3. Birçok dilde bu 1/3, sıfır olan tamsayı bölmesini kullanır . Doğru sonuçları almak için bunun yerine float değişmez değerlerini kullanın, örn h + 1.0/3.0.:
marcus erronius

6
RGB - HSL işlevi çalışmıyor. İşte çalışmayan bir örnek: jsfiddle.net/fs5L02k0/2 ve burada fonksiyon, sabit jsfiddle.net/t5nq6jjc/1 - Formül şu tarihten itibaren kabul edilmiştir: nl.wikipedia.org/wiki/…
Hanna

44

Kurtarmanın en kolay yolunu, python : D

colorsys.hls_to_rgb(h, l, s)

Rengi HLS koordinatlarından RGB koordinatlarına dönüştürün.


6
Python'da böyle standart bir modül olduğuna inanamıyorum! Bu beni gerçekten kurtarıyor. Vikipedi'nin HSL girişindeki dönüşüm algoritmasıyla 2 saattir mücadele ettim. Algoritmanın doğru çıktıyı alamadığı anlaşılıyor.
Ray

2
Ruby eşdeğeri: rubydoc.info/gems/color/1.8/Color/RGB egColor::HSL.new(40,50,60).to_rgb
xxjjnn

1
Tarayıcıda bir renk seçici almak için brython kullanıyorum, bu sadece ihtiyacım olan şey!
EvertW

23

Mohsen kodunun Java uygulaması

Tüm tamsayı şamandıra (yani 1f) olarak bildirildiğini ve şamandıra olması gerektiğini unutmayın, aksi takdirde gri renkleri tercih edersiniz.

HSL - RGB arası

 /**
 * 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 - 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;
}



13

HSL ve RGB için CSS semantiğine kesinlikle uyan bir şey arıyorsanız , CSS 3 belirtiminde belirtilen ve aşağıdakileri okuyan algoritmayı kullanabilirsiniz :

HOW TO RETURN hsl.to.rgb(h, s, l): 
   SELECT: 
      l<=0.5: PUT l*(s+1) IN m2
      ELSE: PUT l+s-l*s IN m2
   PUT l*2-m2 IN m1
   PUT hue.to.rgb(m1, m2, h+1/3) IN r
   PUT hue.to.rgb(m1, m2, h    ) IN g
   PUT hue.to.rgb(m1, m2, h-1/3) IN b
   RETURN (r, g, b)

HOW TO RETURN hue.to.rgb(m1, m2, h): 
   IF h<0: PUT h+1 IN h
   IF h>1: PUT h-1 IN h
   IF h*6<1: RETURN m1+(m2-m1)*h*6
   IF h*2<1: RETURN m2
   IF h*3<2: RETURN m1+(m2-m1)*(2/3-h)*6
   RETURN m1

Bunun diğer cevapların kaynağı olduğuna inanıyorum.


İşte daha basit bir algoritma stackoverflow.com/a/54014428/860099
Kamil Kiełczewski

7

C # Mohsen'in cevabından kod.

Başka biri isterse, Mohsen'in C #'daki cevabının kodu. Not: Colorözel bir sınıftır ve Vector4OpenTK'dan alınmıştır. Her ikisini de seçtiğiniz başka bir şeyle değiştirmek kolaydır.

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;
}

Hsl için Rgba

/// <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);
}


7

Chris'in C # Kodunun Php Uygulaması

Ayrıca buradan , onun matematiğini çok iyi açıklıyor.

Bu temelde HSL'ye ve Hue Doygunluk Hafifliğine dönüştürmek için bir grup işlevdir

PHP 5.6.15 üzerinde test edilmiş ve çalışıyor

TL; DR : Tam kodu Pastebin'de bulabilirsiniz .


Hex - HSL

Giriş: Onaltılık renk biçiminde: [#] 0f4 veya [#] 00ff44 (pound işareti isteğe bağlı)
Çıktı: Derece, Yüzde, Yüzde olarak HSL

/**
 * Input: hex color
 * Output: hsl(in ranges from 0-1)
 * 
 * Takes the hex, converts it to RGB, and sends
 * it to RGBToHsl.  Returns the output.
 * 
*/
function hexToHsl($hex) {
    $r = "";
    $g = "";
    $b = "";

    $hex = str_replace('#', '', $hex);

    if (strlen($hex) == 3) {
        $r = substr($hex, 0, 1);
        $r = $r . $r;
        $g = substr($hex, 1, 1);
        $g = $g . $g;
        $b = substr($hex, 2, 1);
        $b = $b . $b;
    } elseif (strlen($hex) == 6) {
        $r = substr($hex, 0, 2);
        $g = substr($hex, 2, 2);
        $b = substr($hex, 4, 2);
    } else {
        return false;
    }

    $r = hexdec($r);
    $g = hexdec($g);
    $b = hexdec($b);

    $hsl =  rgbToHsl($r,$g,$b);
    return $hsl;
}

RGB - HSL

Giriş: RGB 0-255 aralığında Çıktı: Derece, Yüzde, Yüzde olarak HSL.

/**
 * 
 *Credits:
 * /programming/4793729/rgb-to-hsl-and-back-calculation-problems
 * http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/
 *
 * Called by hexToHsl by default.
 *
 * Converts an RGB color value to HSL. Conversion formula
 * adapted from http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/.
 * Assumes r, g, and b are contained in the range [0 - 255] and
 * returns h, s, and l in the format Degrees, Percent, Percent.
 *
 * @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){  
    //For the calculation, rgb needs to be in the range from 0 to 1. To convert, divide by 255 (ff). 
    $r /= 255;
    $g /= 255;
    $b /= 255;

    $myMax = max($r, $g, $b);
    $myMin = min($r, $g, $b);

    $maxAdd = ($myMax + $myMin);
    $maxSub = ($myMax - $myMin);

    //luminence is (max + min)/2
    $h = 0;
    $s = 0;
    $l = ($maxAdd / 2.0);

    //if all the numbers are equal, there is no saturation (greyscale).
    if($myMin != $myMax){
        if ($l < 0.5) {
            $s = ($maxSub / $maxAdd);
        } else {
            $s = (2.0 - $myMax - $myMin); //note order of opperations - can't use $maxSub here
            $s = ($maxSub / $s);
        }

        //find hue
        switch($myMax){
            case $r: 
                $h = ($g - $b);
                $h = ($h / $maxSub);
                break;
            case $g: 
                $h = ($b - $r); 
                $h = ($h / $maxSub);
                $h = ($h + 2.0);
                break;
            case $b: 
                $h = ($r - $g);
                $h = ($h / $maxSub); 
                $h = ($h + 4.0);
                break;
        } 
    }

    $hsl = hslToDegPercPerc($h, $s, $l);
    return $hsl;
}

HSL (0-1 aralığı) - Derece, Yüzde, Yüzde biçimi

Matematik hesaplamaları için, HSL'nin 0-1 aralığında ele alınması daha kolaydır, ancak insan okunabilirliği için Derece, Yüzde, Yüzde olarak daha kolaydır. Bu işlev HSL'yi 0-1 aralığında alır ve HSL'yi Derece, Yüzde, Yüzde olarak döndürür.

/**
 * Input: HSL in ranges 0-1.
 * Output: HSL in format Deg, Perc, Perc.
 * 
 * Note: rgbToHsl calls this function by default.
 * 
 * Multiplies $h by 60, and $s and $l by 100.
 */
function hslToDegPercPerc($h, $s, $l) {
    //convert h to degrees
    $h *= 60;

    if ($h < 0) {
        $h += 360;
    }

    //convert s and l to percentage
    $s *= 100;
    $l *= 100;

    $hsl['h'] = $h;
    $hsl['s'] = $s;
    $hsl['l'] = $l;
    return $hsl;
}

0-1 aralığında HSL (Derece, Yüzde, Yüzde biçimi) ile HSL

Bu işlev, kolay hesaplama için Derece, Yüzde, Yüzde biçiminde HSL'yi 0-1 aralığına dönüştürür.

/**
 * Input: HSL in format Deg, Perc, Perc
 * Output: An array containing HSL in ranges 0-1
 * 
 * Divides $h by 60, and $s and $l by 100.
 * 
 * hslToRgb calls this by default.
*/
function degPercPercToHsl($h, $s, $l) { 
    //convert h, s, and l back to the 0-1 range

    //convert the hue's 360 degrees in a circle to 1
    $h /= 360;

    //convert the saturation and lightness to the 0-1 
    //range by multiplying by 100
    $s /= 100;
    $l /= 100;

    $hsl['h'] =  $h;
    $hsl['s'] = $s;
    $hsl['l'] = $l;

    return $hsl;
}

HSL - RGB arası

Girdi: HSL formatında Derece, Yüzde, Yüzde Çıktı: RGB formatında 255, 255, 255.

/**
 * Converts an HSL color value to RGB. Conversion formula
 * adapted from http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/.
 * Assumes h, s, and l are in the format Degrees,
 * Percent, Percent, and returns r, g, and b in 
 * the range [0 - 255].
 *
 * Called by hslToHex by default.
 *
 * Calls: 
 *   degPercPercToHsl
 *   hueToRgb
 *
 * @param   Number  h       The hue value
 * @param   Number  s       The saturation level
 * @param   Number  l       The luminence
 * @return  Array           The RGB representation
 */
function hslToRgb($h, $s, $l){
    $hsl = degPercPercToHsl($h, $s, $l);
    $h = $hsl['h'];
    $s = $hsl['s'];
    $l = $hsl['l'];

    //If there's no saturation, the color is a greyscale,
    //so all three RGB values can be set to the lightness.
    //(Hue doesn't matter, because it's grey, not color)
    if ($s == 0) {
        $r = $l * 255;
        $g = $l * 255;
        $b = $l * 255;
    }
    else {
        //calculate some temperary variables to make the 
        //calculation eaisier.
        if ($l < 0.5) {
            $temp2 = $l * (1 + $s);
        } else {
            $temp2 = ($l + $s) - ($s * $l);
        }
        $temp1 = 2 * $l - $temp2;

        //run the calculated vars through hueToRgb to
        //calculate the RGB value.  Note that for the Red
        //value, we add a third (120 degrees), to adjust 
        //the hue to the correct section of the circle for
        //red.  Simalarly, for blue, we subtract 1/3.
        $r = 255 * hueToRgb($temp1, $temp2, $h + (1 / 3));
        $g = 255 * hueToRgb($temp1, $temp2, $h);
        $b = 255 * hueToRgb($temp1, $temp2, $h - (1 / 3));
    }

    $rgb['r'] = $r;
    $rgb['g'] = $g;
    $rgb['b'] = $b;

    return $rgb;
}

Renk Tonu RGB

Tonu ayrı RGB değerlerine dönüştürmek için bu işlev hslToRgb tarafından çağrılır.

/**
 * Converts an HSL hue to it's RGB value.  
 *
 * Input: $temp1 and $temp2 - temperary vars based on 
 * whether the lumanence is less than 0.5, and 
 * calculated using the saturation and luminence
 * values.
 *  $hue - the hue (to be converted to an RGB 
 * value)  For red, add 1/3 to the hue, green 
 * leave it alone, and blue you subtract 1/3 
 * from the hue.
 *
 * Output: One RGB value.
 *
 * Thanks to Easy RGB for this function (Hue_2_RGB).
 * http://www.easyrgb.com/index.php?X=MATH&$h=19#text19
 *
*/
function hueToRgb($temp1, $temp2, $hue) {
    if ($hue < 0) { 
        $hue += 1;
    }
    if ($hue > 1) {
        $hue -= 1;
    }

    if ((6 * $hue) < 1 ) {
        return ($temp1 + ($temp2 - $temp1) * 6 * $hue);
    } elseif ((2 * $hue) < 1 ) {
        return $temp2;
    } elseif ((3 * $hue) < 2 ) {
        return ($temp1 + ($temp2 - $temp1) * ((2 / 3) - $hue) * 6);
    }
    return $temp1;
}

HSL'den Hex'e

Girdi: Biçimde HSL Derece, Yüzde, Yüzde Çıktı: Biçimde onaltılı 00ff22(sayı işareti yok).

RGB'ye, sonra da hex'e dönüştürür.

/**
 * Converts HSL to Hex by converting it to 
 * RGB, then converting that to hex.
 * 
 * string hslToHex($h, $s, $l[, $prependPound = true]
 * 
 * $h is the Degrees value of the Hue
 * $s is the Percentage value of the Saturation
 * $l is the Percentage value of the Lightness
 * $prependPound is a bool, whether you want a pound 
 *  sign prepended. (optional - default=true)
 *
 * Calls: 
 *   hslToRgb
 *
 * Output: Hex in the format: #00ff88 (with 
 * pound sign).  Rounded to the nearest whole
 * number.
*/
function hslToHex($h, $s, $l, $prependPound = true) {
    //convert hsl to rgb
    $rgb = hslToRgb($h,$s,$l);

    //convert rgb to hex
    $hexR = $rgb['r'];
    $hexG = $rgb['g'];
    $hexB = $rgb['b'];

    //round to the nearest whole number
    $hexR = round($hexR);
    $hexG = round($hexG);
    $hexB = round($hexB);

    //convert to hex
    $hexR = dechex($hexR);
    $hexG = dechex($hexG);
    $hexB = dechex($hexB);

    //check for a non-two string length
    //if it's 1, we can just prepend a
    //0, but if it is anything else non-2,
    //it must return false, as we don't 
    //know what format it is in.
    if (strlen($hexR) != 2) {
        if (strlen($hexR) == 1) {
            //probably in format #0f4, etc.
            $hexR = "0" . $hexR;
        } else {
            //unknown format
            return false;
        }
    }
    if (strlen($hexG) != 2) {
        if (strlen($hexG) == 1) {
            $hexG = "0" . $hexG;
        } else {
            return false;
        }
    }
    if (strlen($hexB) != 2) {
        if (strlen($hexB) == 1) {
            $hexB = "0" . $hexB;
        } else {
            return false;
        }
    }

    //if prependPound is set, will prepend a
    //# sign to the beginning of the hex code.
    //(default = true)
    $hex = "";
    if ($prependPound) {
        $hex = "#";
    }

    $hex = $hex . $hexR . $hexG . $hexB;

    return $hex;
}

Düzenleme yaptım rgbToHsl, php kodunuzu güncellemek isteyebilirsiniz. Kodda bir hata var / var. RgbToHsl () s = maxSub / (2 - maxSub)olmalıdırs = maxSub / (2 - maxAdd)
Lex

@Lex Burada ve burada , kodum aslında doğrudur. Sana kafa karıştırıcı olabileceğini düşünüyorum if l < 0.5ile else. Düşüncelerinizi açıklayabilir misiniz? Geri bildirimde bulunmak için zaman ayırdığınız için teşekkür ederiz!
Cullub

1
üzgünüm, haklısın, ama hala bir operasyon sırası sorunu var. # 8cd08c HSL'ye ikinci hesap örneğinde (2 - maxSub) = 1.7333333333333334olduğu gibi bu hesaplamayı kullanarak ( 2 - max - min ) = 0.6352941176470588. Kullanarak 2 - maxAddbeni sürekli olarak photoshops çıktı yakın böylece var doğru olduğunu varsaydı.
Lex

Ah tamam. Bunu işaret ettiğiniz için teşekkürler! Şimdi düzelttim. Umarım bu yardımcı olur!
Cullub

Gerçekten yararlı, bunu JS'ye
Lex

6

Bunu nasıl yapacağımı hatırlamak kolay olan RGB'yi 120 derece aralıkla bir tekerlek üzerinde üç tekerlek teli olarak düşünmektir.

H = hue (0-360)
S = saturation (0-1)
L = luminance (0-1)

R1 = SIN( H ) * L 
G1 = SIN( H + 120 ) * L 
B1 = SIN( H + 240 ) * L 

Zor kısım doygunluktur, ki bu üçünün ortalamasına kadar ölçeklenir.

AVERAGE = (R1 + G1 + B1) / 3 

R2 = ((R1 - AVERAGE) * S) + AVERAGE 
G2 = ((G1 - AVERAGE) * S) + AVERAGE 
B2 = ((B1 - AVERAGE) * S) + AVERAGE 

RED = R2 * 255 
GREEN = G2 * 255 
BLUE = B2 * 255 

Bu kabul edilen cevap olmalı ... çok daha basit ve daha sezgisel! Algoritmayı tersine çevirebilir misiniz?
JoelFan

@JoelFan - Basit ama doğru değil . Orada hiçbir şekilde saf rasyonel ifadeler için (sadece birlikte +, -, *ve /yardımıyla bunları ifade etmek - olarak renk dönüşümleri için tanım tarafından kullanılan -) sineaynı bağımsız (giriş) değişkenlerle fonksiyonlar. Buna rağmen , prensibi anlamak güzeldir (ancak dönüşümleri gerçekleştirmek için değil ).
MarianD

Bu çözümün sorunu, ORTALAMA her zaman ZERO'ya eşittir: (R1 + G1 + B1) = L*[ SIN(H) + SIN(H+120) + SIN(H+240) ]- ve şimdi sin(a)+sin(b) = 2*sin((a+b)/2)*cos((a-b)/2)ilk iki günah için formül kullanırsak : AVERAGE=L*( sin(h+60) + sin(h+240) )ve tekrar AVERAGE= L*2*sin(h+150)*cos(-180/2) = 0alırız (çünkü cos (-180/2) = cos (90) = 0). Yani doygunluk hesaplaması yanlıştır ve aslında doygunluk burada parlaklık olarak çalışır.
Kamil Kiełczewski

@JoelFan Bu çözümle ilgili ikinci sorun, en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB (test örneği: H = 0 için kırmızı renk) ile "uyumlu" sürümüne sahip olmak için H'ye 180 derece eklememiz gerektiğidir. renklerin sayısında hala sorun var - yukarıdaki çözümde sarı, macenta ve camgöbeği renkler ommit ve / veya yanlış şekilde eşleştirilmiştir. Karşılaştırma ile js keman var: jsfiddle.net/Lamik/9s24uc1o/10
Kamil Kiełczewski

3

İşte GLSL'de hızlı, süper basit, dalsız bir sürüm:

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));
}

Bundan daha kısa olamaz ~


Orijinal konsept kanıtına bağlantı: https://www.shadertoy.com/view/XljGzV

(Feragatname: kodum değil!)


2

İşte değiştirilen javascript işlevi, Hue'yu 0-360 derece olarak ayarlar.

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 ; break;
              case g: h = 2 + ( (b - r) / d); break;
              case b: h = 4 + ( (r - g) / d); break;
          }
          h*=60;
          if (h < 0) h +=360;
      }
     return([h, s, l]);
  }  
alert(rgbToHsl(125,115,145));

2

Bunu Brandon Mathis'in HSL Seçici kaynak kodundan aldım .

Başlangıçta CoffeeScript'te yazılmıştır . Çevrimiçi bir dönüştürücü kullanarak JavaScript'e dönüştürdüm ve kullanıcı girişinin geçerli bir RGB değeri olduğunu doğrulama mekanizmasını çıkardım. Bu cevap usecase'im için çalıştı, bu yazıdaki en çok oylanan cevap geçerli bir HSL değeri üretmediğim için bulundu.

Opaklığı / saydamlığı temsil eden bir hsladeğer döndürdüğünü unutmayın a. 0tamamen şeffaf ve 1tamamen opak.

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];
}

Bunu bir Python yöntemi için temel olarak kullandım. Teşekkürler.
JayJay123

posterin istediği gibi bu
HSL'den

1

Bunun yerine RGB'den HSV'ye veya bunun tersine ihtiyacınız olduğunda:

function rgbToHsv(r, g, b)
{
    r /= 255, g /= 255, b /= 255;

    var min = Math.min(r, g, b),
    max = Math.max(r, g, b),
    delta = max - min,
    h = 0, s = 0, v = max;

    if (min != max)
    {
        s = (delta / max);

        switch (max)
        {
            case r: h = (g - b) / delta + (g < b ? 6 : 0); break;
            case g: h = (b - r) / delta + 2; break;
            case b: h = (r - g) / delta + 4; break;
        }

        h /= 6;
    }

    return [h, s, v];
}

function hsvToRgb(h, s, v)
{
    var step = h / (1 / 6),
    pos = step - Math.floor(step), // the hue position within the current step
    m = (Math.floor(step) % 2) ? (1 - pos) * v : pos * v, // mix color value adjusted to the brightness(v)
    max = 1 * v,
    min = (1 - s) * v,
    med = m + ((1 - s) * (v - m)),
    r, g, b;

    switch (Math.floor(step))
    {
        case 0:
            r = max;
            g = med;
            b = min;
            break;
        case 1:
            r = med;
            g = max;
            b = min;
            break;
        case 2:
            r = min;
            g = max;
            b = med;
            break;
        case 3:
            r = min;
            g = med;
            b = max;
            break;
        case 4:
            r = med;
            g = min;
            b = max;
            break;
        case 5:
            r = max;
            g = min;
            b = med;
            break;
    }

    return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}

1

Mohsen'in cevabından Unity3D C # Kodu.

Mohsen'in C #'daki cevabının kodu özellikle Unity3D için hedeflenmiştir. Yukarıda Alec Thilenius tarafından verilen C # cevabından uyarlandı.

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);
    }

}

1

Garry Tan çözümünün RGB'den HSL'ye ve arkaya yanlış dönüştüğünü söyleyen herkes için. Çünkü kodunda sayının kesir kısmını bırakmıştı. Kodunu düzelttim (javascript). Rusça dil bağlantı için özür dilerim, ama ingilizce yok - 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) }
    };
};

1

Javascript ile ayarlanan bir hsl | a color değeri anında rgb | a'ya dönüştürülecektir. Yapmanız gereken tek şey hesaplanan stil değerine erişmek

document.body.style.color = 'hsla(44, 100%, 50%, 0.8)';

console.log(window.getComputedStyle(document.body).color);

// displays: rgba(255, 187, 0, 0.8)

Teknik olarak, sanırım, bu herhangi bir kod satırı bile değil - sadece otomatik olarak yapılır. Böylece, ortamınıza bağlı olarak, sadece bununla kurtulabilirsiniz. Burada çok fazla düşünceli yanıt olmadığı için değil. Amacın ne olduğunu bilmiyorum.

Şimdi, ya rbg | a'dan hsl | a'ya dönüştürmek isterseniz?


1

@Mohsen kodundan daha iyi performansa sahip C ++ uygulaması. Renk tonu için [0-6] aralığı kullanır, bölünme ve 6 ile çarpımı önler. S ve L aralığı [0,1]

void fromRGBtoHSL(float rgb[], float hsl[])
{
     const float maxRGB = max(rgb[0], max(rgb[1], rgb[2]));
     const float minRGB = min(rgb[0], min(rgb[1], rgb[2]));
     const float delta2 = maxRGB + minRGB;
     hsl[2] = delta2 * 0.5f;

     const float delta = maxRGB - minRGB;
     if (delta < FLT_MIN)
         hsl[0] = hsl[1] = 0.0f;
     else
     {
         hsl[1] = delta / (hsl[2] > 0.5f ? 2.0f - delta2 : delta2);
         if (rgb[0] >= maxRGB)
         {
             hsl[0] = (rgb[1] - rgb[2]) / delta;
             if (hsl[0] < 0.0f)
                 hsl[0] += 6.0f;
         }
         else if (rgb[1] >= maxRGB)
             hsl[0] = 2.0f + (rgb[2] - rgb[0]) / delta;
         else
             hsl[0] = 4.0f + (rgb[0] - rgb[1]) / delta;
     }
}

void fromHSLtoRGB(const float hsl[], float rgb[])
{
    if(hsl[1] < FLT_MIN)
        rgb[0] = rgb[1] = rgb[2] = hsl[2];
    else if(hsl[2] < FLT_MIN)
        rgb[0] = rgb[1] = rgb[2] = 0.0f;
    else
    {
        const float q = hsl[2] < 0.5f ? hsl[2] * (1.0f + hsl[1]) : hsl[2] + hsl[1] - hsl[2] * hsl[1];
        const float p = 2.0f * hsl[2] - q;
        float t[] = {hsl[0] + 2.0f, hsl[0], hsl[0] - 2.0f};

        for(int i=0; i<3; ++i)
        {
            if(t[i] < 0.0f)
                t[i] += 6.0f;
            else if(t[i] > 6.0f)
                t[i] -= 6.0f;

            if(t[i] < 1.0f)
                rgb[i] = p + (q - p) * t[i];
            else if(t[i] < 3.0f)
                rgb[i] = q;
            else if(t[i] < 4.0f)
                rgb[i] = p + (q - p) * (4.0f - t[i]);
            else
                rgb[i] = p;
          }
      }
}

0

[0,1] aralığında H, S ve L ile:

ConvertHslToRgb: function (iHsl)
{
    var min, sv, sextant, fract, vsf;

    var v = (iHsl.l <= 0.5) ? (iHsl.l * (1 + iHsl.s)) : (iHsl.l + iHsl.s - iHsl.l * iHsl.s);
    if (v === 0)
        return { Red: 0, Green: 0, Blue: 0 };

    min = 2 * iHsl.l - v;
    sv = (v - min) / v;
    var h = (6 * iHsl.h) % 6;
    sextant = Math.floor(h);
    fract = h - sextant;
    vsf = v * sv * fract;

    switch (sextant)
    {
        case 0: return { r: v, g: min + vsf, b: min };
        case 1: return { r: v - vsf, g: v, b: min };
        case 2: return { r: min, g: v, b: min + vsf };
        case 3: return { r: min, g: v - vsf, b: v };
        case 4: return { r: min + vsf, g: min, b: v };
        case 5: return { r: v, g: min, b: v - vsf };
    }
}

0

Gerçekten hafif bir tane gerekiyordu, Onun% 100 değil, ama bazı kullanımları için yeterince yakın olur.

float3 Hue(float h, float s, float l)
{
    float r = max(cos(h * 2 * UNITY_PI) * 0.5 + 0.5, 0);
    float g = max(cos((h + 0.666666) * 2 * UNITY_PI) * 0.5 + 0.5, 0);
    float b = max(cos((h + 0.333333) * 2 * UNITY_PI) * 0.5 + 0.5, 0);
    float gray = 0.2989 * r + 0.5870 * g + 0.1140 * b;
    return lerp(gray, float3(r, g, b), s) * smoothstep(0, 0.5, l) + 1 * smoothstep(0.5, 1, l);
}

0

@ Mohsen kodunun PHP uygulaması (Test! Dahil)

Bunu yeniden gönderdiğim için üzgünüm. Ama gerçekten ihtiyacım olan kaliteyi veren başka bir uygulama görmedim.

/**
 * 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 */
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.