为什么这个Javascript RGB到HSL代码不起作用?

Kyl*_*iss 13 javascript hsl rgb colors

我在http://www.mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript上找到了这个RGB到HSL脚本.我找不到任何其他小的体面的.问题是这段代码甚至不起作用.有谁知道为什么?(我不知道一点颜色数学,但也许它正在返回补充?)

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];
}
Run Code Online (Sandbox Code Playgroud)

编辑:我跑rgbToHsl(126,210,22)的时候给我[.24,.81,.45],这是橙色的HSL.

Poi*_*nty 23

得到的HSV数组必须被解释为三个分数.对于某些程序,如果要将HSV表示为整数,则将"H"值乘以360,将"S"和"V"值乘以100.您引用绿色RGB的HSV值[126,210, [是]整数中的HSV [87,81,45].如果要执行以下操作,可以更改函数以返回此类整数:

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 [Math.floor(h * 360), Math.floor(s * 100), Math.floor(l * 100)];
}
Run Code Online (Sandbox Code Playgroud)

[编辑]说,它仍然给我一些亮度很高的东西("L"或"V")太暗了; Gimp说HSV值应该是[90,80,82],或者是分数[.20,.80,.82].

[另一个编辑]一个问题可能是HSL和HSV是不同的方案......仍在环顾四周.

好的,如果有人想要RGB到HSV(就像你在Gimp中看到的那样),这里有一个版本:

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

    v = Math.floor(max / 255 * 100);
    if ( max != 0 )
        s = Math.floor(delta / max * 100);
    else {
        // black
        return [0, 0, 0];
    }

    if( r == max )
        h = ( g - b ) / delta;         // between yellow & magenta
    else if( g == max )
        h = 2 + ( b - r ) / delta;     // between cyan & yellow
    else
        h = 4 + ( r - g ) / delta;     // between magenta & cyan

    h = Math.floor(h * 60);            // degrees
    if( h < 0 ) h += 360;

    return [h, s, v];
}
Run Code Online (Sandbox Code Playgroud)

  • @BrunoLM哇谢谢!! 就个人而言,我目前没有使用此类代码(在我当前的网站上),但您对细节和完整性的关注肯定会改善未来Stackoverflow客户的体验:-) (3认同)
  • 以下是您的代码,其中包含针对此案例的修复程序以及我在其他网站上找到的"HsvToRgb":http://stackoverflow.com/questions/5833624/increase-css-brightness-color-on-click-with-jquery-的JavaScript/5834079#5834079 (2认同)

Kam*_*ski 7

简短但准确

看起来您的代码没问题(但它返回 Hue=0.24 - 将其乘以 360 度以获得角度整数值) - 但是试试这个更短的代码(更多:hsl2rgbrgb2hsvhsv2rgbsl22sv):

// in: r,g,b in [0,1], out: h in [0,360) and s,l in [0,1]
function rgb2hsl(r,g,b) {
  let v=Math.max(r,g,b), c=v-Math.min(r,g,b), f=(1-Math.abs(v+v-c-1)); 
  let h= c && ((v==r) ? (g-b)/c : ((v==g) ? 2+(b-r)/c : 4+(r-g)/c)); 
  return [60*(h<0?h+6:h), f ? c/f : 0, (v+v-c)/2];
}
Run Code Online (Sandbox Code Playgroud)

// in: r,g,b in [0,1], out: h in [0,360) and s,l in [0,1]
function rgb2hsl(r,g,b) {
  let v=Math.max(r,g,b), c=v-Math.min(r,g,b), f=(1-Math.abs(v+v-c-1)); 
  let h= c && ((v==r) ? (g-b)/c : ((v==g) ? 2+(b-r)/c : 4+(r-g)/c)); 
  return [60*(h<0?h+6:h), f ? c/f : 0, (v+v-c)/2];
}
Run Code Online (Sandbox Code Playgroud)
function rgb2hsl(r,g,b) {
  let v=Math.max(r,g,b), c=v-Math.min(r,g,b), f=(1-Math.abs(v+v-c-1)); 
  let h= c && ((v==r) ? (g-b)/c : ((v==g) ? 2+(b-r)/c : 4+(r-g)/c)); 
  return [60*(h<0?h+6:h), f ? c/f : 0, (v+v-c)/2];
}

console.log(`rgb: (0.36,0.3,0.24) --> hsl: (${rgb2hsl(0.36,0.3,0.24)})`);


// ---------------
// UX
// ---------------

rgb= [0,0,0];
hs= [0,0,0];

let $ = x => document.querySelector(x);

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

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(', ')
  tr = `RGB: ${rr}`
  th = `HSL: ${hs.map((x,i)=>i? (x*100).toFixed(2)+'%':x|0).join(', ')}`
  $('.box').style.backgroundColor=`rgb(${rr})`;  
  $('.infoRGB').innerHTML=`${tr}`;  
  $('.infoHS').innerHTML =`${th}`;  
  
  $('#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;  
}

refresh();
Run Code Online (Sandbox Code Playgroud)
.box {
  width: 50px;
  height: 50px;
  margin: 20px;
}

body {
    display: flex;
}
Run Code Online (Sandbox Code Playgroud)

我开发了 S_HSL wiki公式(用绿色边框标记) - 其中 MAX=max(r,g,b) 和 MIN=min(r,g,b) - 在上面的代码中,我做了一些改进并进行了分析以显示结果是正确的。这让我在最后得到很短的代码

在此处输入图片说明