Colors RGB到HSL转换

Colors RGB到HSL转换,colors,converter,rgb,hsl,Colors,Converter,Rgb,Hsl,我正在创建一个颜色选择器工具,对于HSL滑块,我需要能够将RGB转换为HSL。当我寻找转换的方法时,我发现了这个问题 虽然它提供了一个从RGB到HSL转换的函数,但我看不到对计算中真正发生的事情的解释。为了更好地理解它,我读了维基百科上的 稍后,我使用“HSL和HSV”页面中的计算重写了“HSL到RGB颜色转换”的函数 如果R是最大值,我就无法计算色调。参见“HSL和HSV”页面中的计算: 这是另一个荷兰语的: 这是从“HSL到RGB颜色转换”: 案例r:h=(g-b)/d+(g

我正在创建一个颜色选择器工具,对于HSL滑块,我需要能够将RGB转换为HSL。当我寻找转换的方法时,我发现了这个问题

虽然它提供了一个从RGB到HSL转换的函数,但我看不到对计算中真正发生的事情的解释。为了更好地理解它,我读了维基百科上的

稍后,我使用“HSL和HSV”页面中的计算重写了“HSL到RGB颜色转换”的函数

如果R是最大值,我就无法计算色调。参见“HSL和HSV”页面中的计算:

这是另一个荷兰语的:

这是从“HSL到RGB颜色转换”:

案例r:h=(g-b)/d+(g
我用几个RGB值测试了所有三个,它们似乎产生了类似的结果(如果不精确的话)。我想知道的是他们在做同样的事情吗?对于某些特定的RGB值,我会得到不同的结果吗?我应该用哪一个

hue = (g - b) / c;                   // dutch wiki
hue = ((g - b) / c) % 6;             // eng wiki
hue = (g - b) / c + (g < b ? 6 : 0); // SO answer
色调=(g-b)/c;//荷兰维基 色调=((g-b)/c)%6;//英语维基 色调=(g-b)/c+(g

功能rgb2hsl(r、g、b){
//看https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation
//将r,g,b[0255]范围转换为[0,1]
r=r/255,
g=g/255,
b=b/255;
//求r,g,b的最小值和最大值
var max=数学最大值(r,g,b);
var min=数学min(r,g,b);
//亮度是最大和最小颜色分量的平均值
变量lum=(最大+最小)/2;
色变;
var-sat;
如果(max==min){//无饱和
色调=0;
sat=0;
}否则{
var c=max-min;//色度
//饱和度只是按比例缩放以填充的色度
//色调和亮度的每种组合的间隔[0,1]
sat=c/(1-数学绝对值(2*lum-1));
开关(最大值){
案例r:
//色调=(g-b)/c;
//色调=((g-b)/c)%6;
//色调=(g-b)/c+(g
继续我的评论,英文版看起来是正确的,但我不确定荷兰语版中发生了什么,因为我不理解WIKI页面

下面是我从英文WIKI页面制作的ES6版本,以及一些与WIKI示例匹配的示例数据(给出或接受Javascript的数字精度)。希望它在创建自己的函数时有用

//请参见:https://en.wikipedia.org/wiki/RGB_color_model
//见:https://en.wikipedia.org/wiki/HSL_and_HSV
//期望R、G、B、Cmax和色度在数字区间[0,1]
//如果色度为0或数字间隔[0,360]度,则返回未定义
功能色调(R、G、B、Cmax、色度){
让H;
如果(色度===0){
返回H;
}
如果(Cmax==R){
H=((G-B)/色度)%6;
}否则如果(Cmax==G){
H=((B-R)/色度)+2;
}否则如果(Cmax==B){
H=((R-G)/色度)+4;
}
H*=60;
返回H<0?H+360:H;
}
//返回提供的数字参数的平均值
函数平均值(…theArgs){
返回args.length?args.reduce((p,c)=>p+c,0)/args.length:0;
}
//期望R、G、B、Cmin、Cmax和色度在数字区间[0,1]
//类型默认为“双六角锥”公式
//为备选方案设置“luma601”或“luma709”
//见:https://en.wikipedia.org/wiki/Luma_(视频)
//返回一个数字间隔[0,1]
函数亮度(R、G、B、Cmin、Cmax,类型=‘双六角锥’){
如果(类型=='luma601'){
回报率(0.299*R)+(0.587*G)+(0.114*B);
}
如果(类型=='luma709'){
返回(0.2126*R)+(0.7152*G)+(0.0772*B);
}
返回平均值(Cmin,Cmax);
}
//期望L和色度在数字间隔[0,1]内
//返回一个数字间隔[0,1]
功能饱和度(L,色度){
返回色度===0?0:chroma/(1-Math.abs(2*L-1));
}
//将值返回到固定位数
函数toFixed(值、数字){
返回Number.isFinite(value)和&Number.isFinite(digits)?value.toFixed(digits):值;
}
//期望R、G和B在数字间隔[0,1]内
//以适当的间隔和数字返回H、S和L的映射
函数RGB2HSL(R、G、B、fixed=true){
常数Cmin=数学最小值(R,G,B);
常数Cmax=数学最大值(R,G,B);
常数色度=Cmax-Cmin;
//默认的“双六角锥”方程
常数L=亮度(R、G、B、Cmin、Cmax);
//H,以度为单位间隔[0,360]
//区间[0,1]中的L和S
返回新地图([
['H',固定(色调(R、G、B、Cmax、色度),固定和&1)],
['S',toFixed(饱和度(L,色度),固定和&3)],
['L',固定(L,固定和&3)]
]);
}
//期望值为间隔[0,255]中的数字
//以数字间隔[0,1]的形式返回标准化值
函数颜色范围(值){
返回值/255;
};
//期望R、G和B在数字间隔[0255]内
功能RGBdec2HSL(R、G、B){
返回RGB2HSL(颜色范围(R)、颜色范围(G)、颜色范围(B));
}
//将十六进制字符串转换为十进制数
函数hex2dec(值){
返回parseInt(值,16);
}
//将字符串切分为成对字符的数组
函数pairSlicer(值){
返回值.match(/../g);
}
//将“0”前置到字符串的开头,并指定长度
函数prePad(值、计数){
返回('0')。重复(计数)+值。切片(-计数);
}
//从值格式化十六进制对字符串
函数十六进制对(值){
返回hex2dec(prePad(值,2));
}
//期望R、G和B为十六进制字符串
hue = (g - b) / c;                   // dutch wiki
hue = ((g - b) / c) % 6;             // eng wiki
hue = (g - b) / c + (g < b ? 6 : 0); // SO answer
function rgb2hsl(r, g, b) {
    // see https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation
    // convert r,g,b [0,255] range to [0,1]
    r = r / 255,
    g = g / 255,
    b = b / 255;
    // get the min and max of r,g,b
    var max = Math.max(r, g, b);
    var min = Math.min(r, g, b);
    // lightness is the average of the largest and smallest color components
    var lum = (max + min) / 2;
    var hue;
    var sat;
    if (max == min) { // no saturation
        hue = 0;
        sat = 0;
    } else {
        var c = max - min; // chroma
        // saturation is simply the chroma scaled to fill
        // the interval [0, 1] for every combination of hue and lightness
        sat = c / (1 - Math.abs(2 * lum - 1));
        switch(max) {
            case r:
                // hue = (g - b) / c;
                // hue = ((g - b) / c) % 6;
                // hue = (g - b) / c + (g < b ? 6 : 0);
                break;
            case g:
                hue = (b - r) / c + 2;
                break;
            case b:
                hue = (r - g) / c + 4;
                break;
        }
    }
    hue = Math.round(hue * 60); // °
    sat = Math.round(sat * 100); // %
    lum = Math.round(lum * 100); // %
    return [hue, sat, lum];
}
R = R / 255    R =  51 / 255 = 0.2
G = G / 255    G = 153 / 255 = 0.6
B = B / 255    B = 204 / 255 = 0.8
M = max(R, G, B)    M = max(0.2, 0.6, 0.8) = 0.8
m = min(R, G, B)    m = min(0.2, 0.6, 0.8) = 0.2
C = OP / OP'
C = M - m
C = 0.8- 0.2 = 0.6
segment = (R - G) / C = (0.2 - 0.6) / 0.6 = -0.6666666666666666
segment = (R - G) / C = (0.2 - 0.6) / 0.6 = -0.6666666666666666
RYGCP   = segment + 4 = 3.3333333333333335
H' = 3.3333333333333335
H  = H' * 60 = 200°
function RGBToHSL(r,g,b) {
  // Make r, g, and b fractions of 1
  r /= 255;
  g /= 255;
  b /= 255;

  // Find greatest and smallest channel values
  let cmin = Math.min(r,g,b),
      cmax = Math.max(r,g,b),
      delta = cmax - cmin,
      h = 0,
      s = 0,
      l = 0;

  // Calculate hue
  // No difference
  if (delta == 0)
    h = 0;
  // Red is max
  else if (cmax == r)
    h = ((g - b) / delta) % 6;
  // Green is max
  else if (cmax == g)
    h = (b - r) / delta + 2;
  // Blue is max
  else
    h = (r - g) / delta + 4;

  h = Math.round(h * 60);

  // Make negative hues positive behind 360°
  if (h < 0)
      h += 360;

  // Calculate lightness
  l = (cmax + cmin) / 2;

  // Calculate saturation
  s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));

  // Multiply l and s by 100
  s = +(s * 100).toFixed(1);
  l = +(l * 100).toFixed(1);

  return "hsl(" + h + "," + s + "%," + l + "%)";
}