【问题标题】:How to Use HSL to RGB Conversion Function如何使用 HSL 转 RGB 功能
【发布时间】:2014-12-26 06:44:56
【问题描述】:

感觉我在这里遗漏了一些非常简单的东西,但我无法从HSL to RGB color conversion 的答案中获得公式。有问题的功能是:

function hslToRgb(h, s, l){
    var r, g, b;

    if(s == 0){
        r = g = b = l; // achromatic
    }else{
        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)];
}

我相信,我的问题是关于输入什么作为我的“h”参数。通常,在 CSS 或 Photoshop 中使用 HSL 时,色调值是 0 到 360 之间的数字,但此函数需要 0 到 1 之间的值。有人可以向我解释一下我将如何转换色调值240 到 0 和 1 之间的等效值,所以我可以将它代入这个公式吗?我尝试将 240 除以 360,但这不起作用。

【问题讨论】:

  • 它到底是怎么回事?映射 [0 - 360] -> [0 - 1] 的唯一方法是除以 360。见 similar question
  • r、g 和 b 的结果值不正确。当我将相同的 hsl 值插入 Photoshop 中的颜色选择器时,生成的 rgb 值与此函数返回的值大不相同。
  • 当我将色调除以 360 时,我得到了正确的转换。我只是从hslpicker.com 获取颜色,并在rgbtool.com 输入转换结果你的 s & l 值是否也在[0, 1] 的范围?
  • 是的。例如,我只是为 100 的色调执行 console.log(hslToRgb(.27777777777778, .81, .45));。在 Photoshop 和 rgbtool.com 中,我得到了结果 r53、g115、b22,但函数输出 r84、g208、b22。诡异的。我所做的只是复制和粘贴函数,所以我真的不知道会发生什么。
  • 由于 H 的微小变化,RGB 也出现了意想不到的跳跃。

标签: javascript colors


【解决方案1】:

看起来原来的算法是错误的。根据wikipedia,您可以获得独立于色调的色度和亮度调整(因此 b 值相似),但其他任何事情都需要更多的数学运算——特别是模数。看起来该算法不能很好地处理该特定转换,特别是考虑到它期望色调在 [0, 1] 范围内。试试这个算法:

// expected hue range: [0, 360)
// expected saturation range: [0, 1]
// expected lightness range: [0, 1]
var hslToRgb = function(hue, saturation, lightness){
  // based on algorithm from http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB
  if( hue == undefined ){
    return [0, 0, 0];
  }

  var chroma = (1 - Math.abs((2 * lightness) - 1)) * saturation;
  var huePrime = hue / 60;
  var secondComponent = chroma * (1 - Math.abs((huePrime % 2) - 1));

  huePrime = Math.floor(huePrime);
  var red;
  var green;
  var blue;

  if( huePrime === 0 ){
    red = chroma;
    green = secondComponent;
    blue = 0;
  }else if( huePrime === 1 ){
    red = secondComponent;
    green = chroma;
    blue = 0;
  }else if( huePrime === 2 ){
    red = 0;
    green = chroma;
    blue = secondComponent;
  }else if( huePrime === 3 ){
    red = 0;
    green = secondComponent;
    blue = chroma;
  }else if( huePrime === 4 ){
    red = secondComponent;
    green = 0;
    blue = chroma;    
  }else if( huePrime === 5 ){
    red = chroma;
    green = 0;
    blue = secondComponent;
  }

  var lightnessAdjustment = lightness - (chroma / 2);
  red += lightnessAdjustment;
  green += lightnessAdjustment;
  blue += lightnessAdjustment;

  return [Math.round(red * 255), Math.round(green * 255), Math.round(blue * 255)];

};

它可能会在一些边缘情况下失败,但这些应该很容易解决

【讨论】:

  • 那是个了不起的人。真的很感谢你花时间。我确实尝试了一些不同的设置,并且大多数都有效。但是我确实找到了一个没有的(hslToRgb(320, 0.44, 0.54)),它似乎返回了 3 个正确的数字,但是绿色和蓝色的值被切换了。不确定这是否是您所说的一些可能失败的边缘情况的意思。无论如何,我真的很感激。
  • 太棒了。再次感谢!
猜你喜欢
  • 2012-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
  • 2015-10-15
  • 2011-03-29
  • 2011-01-22
  • 2020-11-28
相关资源
最近更新 更多