将 HSB/HSV 颜色转换为 HSL

发布于 2024-09-13 16:48:34 字数 324 浏览 9 评论 0 原文

如何将 HSB 颜色转换为 HSL?

Photoshop 在其颜色选择器中显示 HSB 颜色。 HSB 颜色不能在 CSS 中使用,但 HSL 可以。

我尝试了这个JS:

function hsb2hsl(h, s, b) {
  return {
    h: h,
    s: s,
    l: b-s/2
  }
}

但是 hsb2hsl(0, 100, 50).l == 0 而不是 25

更新: 我可以这样做吗?转换 HSB → RGB → HSL?

How do I convert HSB color to HSL?

Photoshop shows HSB color in its color picker. HSB color cannot be used in CSS, but HSL can.

I tried this JS:

function hsb2hsl(h, s, b) {
  return {
    h: h,
    s: s,
    l: b-s/2
  }
}

But hsb2hsl(0, 100, 50).l == 0 instead of 25

Update: Can I do that without converting HSB → RGB → HSL?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

时光磨忆 2024-09-20 16:48:34

简短但精确

试试这个([0,1] 中的 s,v,l,更多:hsv2rgb rgb2hsvhsl2rgb rgb2hsl

let hsl2hsv = (h,s,l,v=s*Math.min(l,1-l)+l) => [h, v?2-2*l/v:0, v];

let hsv2hsl = (h,s,v,l=v-v*s/2, m=Math.min(l,1-l)) => [h,m?(v-l)/m:0,l];

let hsv2hsl = (h,s,v,l=v-v*s/2,m=Math.min(l,1-l)) => [h,m?(v-l)/m:0,l];
let hsl2hsv = (h,s,l,v=s*Math.min(l,1-l)+l) => [h, v?2-2*l/v:0, v];

console.log("hsv:["+ hsl2hsv(30,1,0.6) +"] hsl:["+ hsv2hsl(30,0.8,1) +"]");


// -------------------
// UI code
// -------------------

let $ = x => document.querySelector(x);
let c = (x,s) => $(x).style.backgroundColor=s;
let hsl=[0,1,0.5];
let hsv=hsl2hsv(...hsl);

let refreshHSV =(i,e) => {
   hsv[i]= e.target.value/(i?100:1);
   hsl=hsv2hsl(...hsv);
   refreshView();
}

let refreshHSL =(i,e) => {
   hsl[i]= e.target.value/(i?100:1);
   hsv=hsl2hsv(...hsl);  
   refreshView();
}

let hsv2rgb = (h,s,v) => {                              
  let f= (n,k=(n+h/60)%6) => v - v*s*Math.max( Math.min(k,4-k,1), 0);     
  return [f(5),f(3),f(1)];       
}

let refreshView = () => {
   let a= [hsl[0], (hsl[1]*100).toFixed(2), (hsl[2]*100).toFixed(2)]; 
   let b= [hsv[0], (hsv[1]*100).toFixed(2), (hsv[2]*100).toFixed(2)]; 
   
   let r= hsv2rgb(...hsv).map(x=>x*255|0);
   let ta= `hsl(${a[0]},${a[1]}%,${a[2]}%)`
   let tb= `hsv(${b[0]},${b[1]}%,${b[2]}%)`
   let tr= `rgb(${r[0]},${r[1]},${r[2]})`
   
   c('.hsl', tr);   
   $('#sv').value=hsv[1]*100;
   $('#v').value =hsv[2]*100;
   $('#sl').value=hsl[1]*100;
   $('#l').value =hsl[2]*100;
   $('.info').innerHTML=`${tr}\n${tb}\n${ta.padEnd(25)}`;   
}



refreshView();
.box {
  width: 50px;
  height: 50px;
  margin: 20px;
}

body {
    display: flex;
    background: white;
}
<div>
<input id="h" type="range" min="0" max="360" value="0" oninput="refreshHSV(0,event)">Hue<br>
<div class="box hsl"></div>
<pre class="info"></pre>
</div> 

<div>
<input id="sv" type="range" min="0" max="100" value="0" oninput="refreshHSV(1,event)">HSV Saturation<br>
<input id="v" type="range" min="0" max="100" value="100" oninput="refreshHSV(2,event)">HSV Value<br><br><br>
<input id="sl" type="range" min="0" max="100" value="0" oninput="refreshHSL(1,event)">HSL Saturation<br>
<input id="l" type="range" min="0" max="100" value="100" oninput="refreshHSL(2,event)">HSL Lightness<br>
</div>

此代码基于我在 wiki 上发现并编写的公式

在此处输入图像描述

Short but precise

Try this (s,v,l in [0,1], more: hsv2rgb rgb2hsv and hsl2rgb rgb2hsl)

let hsl2hsv = (h,s,l,v=s*Math.min(l,1-l)+l) => [h, v?2-2*l/v:0, v];

let hsv2hsl = (h,s,v,l=v-v*s/2, m=Math.min(l,1-l)) => [h,m?(v-l)/m:0,l];

let hsv2hsl = (h,s,v,l=v-v*s/2,m=Math.min(l,1-l)) => [h,m?(v-l)/m:0,l];
let hsl2hsv = (h,s,l,v=s*Math.min(l,1-l)+l) => [h, v?2-2*l/v:0, v];

console.log("hsv:["+ hsl2hsv(30,1,0.6) +"] hsl:["+ hsv2hsl(30,0.8,1) +"]");


// -------------------
// UI code
// -------------------

let $ = x => document.querySelector(x);
let c = (x,s) => $(x).style.backgroundColor=s;
let hsl=[0,1,0.5];
let hsv=hsl2hsv(...hsl);

let refreshHSV =(i,e) => {
   hsv[i]= e.target.value/(i?100:1);
   hsl=hsv2hsl(...hsv);
   refreshView();
}

let refreshHSL =(i,e) => {
   hsl[i]= e.target.value/(i?100:1);
   hsv=hsl2hsv(...hsl);  
   refreshView();
}

let hsv2rgb = (h,s,v) => {                              
  let f= (n,k=(n+h/60)%6) => v - v*s*Math.max( Math.min(k,4-k,1), 0);     
  return [f(5),f(3),f(1)];       
}

let refreshView = () => {
   let a= [hsl[0], (hsl[1]*100).toFixed(2), (hsl[2]*100).toFixed(2)]; 
   let b= [hsv[0], (hsv[1]*100).toFixed(2), (hsv[2]*100).toFixed(2)]; 
   
   let r= hsv2rgb(...hsv).map(x=>x*255|0);
   let ta= `hsl(${a[0]},${a[1]}%,${a[2]}%)`
   let tb= `hsv(${b[0]},${b[1]}%,${b[2]}%)`
   let tr= `rgb(${r[0]},${r[1]},${r[2]})`
   
   c('.hsl', tr);   
   $('#sv').value=hsv[1]*100;
   $('#v').value =hsv[2]*100;
   $('#sl').value=hsl[1]*100;
   $('#l').value =hsl[2]*100;
   $('.info').innerHTML=`${tr}\n${tb}\n${ta.padEnd(25)}`;   
}



refreshView();
.box {
  width: 50px;
  height: 50px;
  margin: 20px;
}

body {
    display: flex;
    background: white;
}
<div>
<input id="h" type="range" min="0" max="360" value="0" oninput="refreshHSV(0,event)">Hue<br>
<div class="box hsl"></div>
<pre class="info"></pre>
</div> 

<div>
<input id="sv" type="range" min="0" max="100" value="0" oninput="refreshHSV(1,event)">HSV Saturation<br>
<input id="v" type="range" min="0" max="100" value="100" oninput="refreshHSV(2,event)">HSV Value<br><br><br>
<input id="sl" type="range" min="0" max="100" value="0" oninput="refreshHSL(1,event)">HSL Saturation<br>
<input id="l" type="range" min="0" max="100" value="100" oninput="refreshHSL(2,event)">HSL Lightness<br>
</div>

This code based on formulas which I discover and write on wiki

enter image description here

柠檬色的秋千 2024-09-20 16:48:34

我认为这是最准确的:

function hsv_to_hsl(h, s, v) {
    // both hsv and hsl values are in [0, 1]
    var l = (2 - s) * v / 2;

    if (l != 0) {
        if (l == 1) {
            s = 0;
        } else if (l < 0.5) {
            s = s * v / (l * 2);
        } else {
            s = s * v / (2 - l * 2);
        }
    }

    return [h, s, l];
}

I think this is the most precise:

function hsv_to_hsl(h, s, v) {
    // both hsv and hsl values are in [0, 1]
    var l = (2 - s) * v / 2;

    if (l != 0) {
        if (l == 1) {
            s = 0;
        } else if (l < 0.5) {
            s = s * v / (l * 2);
        } else {
            s = s * v / (2 - l * 2);
        }
    }

    return [h, s, l];
}
梦归所梦 2024-09-20 16:48:34

Stephen Morley 似乎已经在这里解决了这个问题。

具体来说:

/* Calculates and stores the HSL components of this HSVColour so that they can
 * be returned be the getHSL function.
 */
function calculateHSL(){
  // determine the lightness in the range [0,100]
  var l = (2 - hsv.s / 100) * hsv.v / 2;

  // store the HSL components
  hsl =
    {
      'h' : hsv.h,
      's' : hsv.s * hsv.v / (l < 50 ? l * 2 : 200 - l * 2),
      'l' : l
    };

  // correct a division-by-zero error
  if (isNaN(hsl.s)) hsl.s = 0;
}

他使用 [0-360] 作为色调,使用 [0-100] 作为其他值。

Stephen Morley seems to have nailed it here.

Specifically:

/* Calculates and stores the HSL components of this HSVColour so that they can
 * be returned be the getHSL function.
 */
function calculateHSL(){
  // determine the lightness in the range [0,100]
  var l = (2 - hsv.s / 100) * hsv.v / 2;

  // store the HSL components
  hsl =
    {
      'h' : hsv.h,
      's' : hsv.s * hsv.v / (l < 50 ? l * 2 : 200 - l * 2),
      'l' : l
    };

  // correct a division-by-zero error
  if (isNaN(hsl.s)) hsl.s = 0;
}

He uses [0-360] for hue and [0-100] for the other values.

秋日私语 2024-09-20 16:48:34

首先,您的运算顺序将导致:

b - s / 2 =
50 - 100 / 2 =
50 - 50 = 0

因为除法运算符的优先级高于减法。如果您期望 25,则需要改为 (b - s) / 2

不过,我不太确定这个结果是否是您想要的。由于 B (V) 和 L 的定义都是基于 RGB 色彩空间,因此您至少需要一种方法来恢复 Mm 的值来计算转换。

有关详细信息,请参阅维基百科文章。

First of all, your order of operations will result in:

b - s / 2 =
50 - 100 / 2 =
50 - 50 = 0

because the division operator has higher precedence than subtraction. If you're expecting 25, you need to do (b - s) / 2 instead.

I'm not exactly sure that this result is what you want, however. Since the definitions of both B (V) and L are based on the RGB colorspace, you need at least a way to recover the values of M and m to calculate the conversion.

See the Wikipedia article for more information.

心是晴朗的。 2024-09-20 16:48:34

维基百科不再显示 Kamil Kiełczewski 所示的公式。它们现在看起来像这样:

const hsvToHsl = (h, s, v, l = v * (1 - (s / 2))) => [h, l === 0 || l === 1 ? 0 : (v - l) / Math.min(l, 1 - l), l];
const hslToHsv = (h, s, l, v = l + s * Math.min(l, 1 - l)) => [h, v === 0 ? 0 : 2 * (1 - (l / v)), v];

在此处输入图像描述

Wikipedia no longer shows the formulas shown by Kamil Kiełczewski. They now look like this:

const hsvToHsl = (h, s, v, l = v * (1 - (s / 2))) => [h, l === 0 || l === 1 ? 0 : (v - l) / Math.min(l, 1 - l), l];
const hslToHsv = (h, s, l, v = l + s * Math.min(l, 1 - l)) => [h, v === 0 ? 0 : 2 * (1 - (l / v)), v];

enter image description here

叫思念不要吵 2024-09-20 16:48:34

您可以尝试使用 Tinycolor 库。
要从 HSV 转换为 HSL,您可以执行此

tinycolor("hsv(34, 56%, 100%)").toHslString()

您应该得到如下结果:“hsl(34, 100) %, 72%)"

You can try using Tinycolor library.
To convert from HSV to HSL you could do this

tinycolor("hsv(34, 56%, 100%)").toHslString()

you should get result somethng like this : "hsl(34, 100%, 72%)"

从﹋此江山别 2024-09-20 16:48:34

我使用其他答案中的函数得到了错误的结果。现在得到了这些似乎运行良好的:

function hsb_to_hsl(h, s, b) {
    const x = (200 - s) * b / 100;
    return {
        h,
        s: x === 0 || x === 200 ? 0 : Math.round(s * b / (x <= 100 ? x : 200 - x)),
        l: Math.round(x / 2)
    };
}

function hsl_to_hsb(h, s, l) {
    const x = s * (l < 50 ? l : 100 - l);
    const b = l + (x / 100);
    return {
        h,
        s: l === 0 ? s : 2 * x / b,
        b
    };
}

I got wrong results with the functions in other answers. Now got these that seem to work well:

function hsb_to_hsl(h, s, b) {
    const x = (200 - s) * b / 100;
    return {
        h,
        s: x === 0 || x === 200 ? 0 : Math.round(s * b / (x <= 100 ? x : 200 - x)),
        l: Math.round(x / 2)
    };
}

function hsl_to_hsb(h, s, l) {
    const x = s * (l < 50 ? l : 100 - l);
    const b = l + (x / 100);
    return {
        h,
        s: l === 0 ? s : 2 * x / b,
        b
    };
}
夏天碎花小短裙 2024-09-20 16:48:34

不同颜色空间之间的转换公式有很多: http://www.easyrgb.com/?X =数学

There are a lot of conversion formulas between different color spaces: http://www.easyrgb.com/?X=MATH

我一直都在从未离去 2024-09-20 16:48:34

恐怕我的 Javascript 知识缺乏,但你应该能够从 http://ariya.blogspot.com/2008/07/converting- Between-hsl-and-hsv.html

I'm afraid my Javascript knowledge is lacking, but you should be able to infer the conversion from http://ariya.blogspot.com/2008/07/converting-between-hsl-and-hsv.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文