aki*_*uri 25 hsl rgb colors converter
我正在创建一个拾色器工具,对于HSL滑块,我需要能够将RGB转换为HSL.当我搜索SO以进行转换的方法时,我发现这个问题HSL到RGB颜色转换.
虽然它提供了从RGB转换到HSL的功能,但我没有看到计算中实际发生的事情的解释.为了更好地理解它,我在维基百科上阅读了HSL和HSV.
后来,我使用"HSL和HSV"页面中的计算重写了"HSL到RGB颜色转换"的功能.
如果R是最大值,我会坚持计算色调.请参阅"HSL和HSV"页面中的计算:
这是来自荷兰语的另一个维基页面:
这是从"HSL到RGB颜色转换" 的答案:
case r: h = (g - b) / d + (g < b ? 6 : 0); break; // d = max-min = c
Run Code Online (Sandbox Code Playgroud)
我已经用几个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
Run Code Online (Sandbox Code Playgroud)
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];
}
Run Code Online (Sandbox Code Playgroud)
aki*_*uri 73
我一直在阅读几个维基页面并检查不同的计算,并创建RGB立方体投影到六边形的可视化.我想发表我对这种转换的理解.由于我发现这种转换(使用几何形状的颜色模型的表示)很有趣,我会尽量做到尽可能彻底.首先,让我们从RGB开始.
嗯,这真的不需要太多解释.在最简单的形式中,您有3个值,R,G和B,范围为[0,255].例如,51,153,204.我们可以使用条形图来表示它:
我们还可以在3D空间中表示颜色.我们有三个值R,G,B对应于X,Y和Z.所有三个值都在该[0,255]范围内,从而产生一个立方体.但在创建RGB立方体之前,让我们首先处理2D空间.R,G,B的两种组合给出了:RG,RB,GB.如果我们要在飞机上绘制这些图表,我们会得到以下结果:
这些是RGB立方体的前三个方面.如果我们将它们放在3D空间中,它会产生一个半立方体:
如果你检查上面的图表,通过混合两种颜色,我们得到一个新的颜色(255,255),这些是黄色,洋红色和青色.同样,这两种组合给我们:YM,YC和MC.这些是立方体缺失的一面.一旦我们添加它们,我们就会获得一个完整的立方
并且51,153,204在这个立方体中的位置:
现在我们有了RGB立方体,让它将它投射到六边形上.首先,我们将立方体倾斜45° x,然后再倾斜35.264° y.第二次倾斜后,黑色角落在底部,白色角落在顶部,它们都穿过z轴.
如您所见,当我们从顶部查看立方体时,我们可以使用正确的色调顺序获得我们想要的六边形外观.但我们需要把它投射到一个真正的六边形上.我们所做的是绘制一个与立方体顶视图大小相同的六边形.六角形的所有角都对应于立方体的角和颜色,并且立方体的顶角是白色,投影到六边形的中心.黑色被省略.如果我们将每种颜色映射到六边形上,我们就会看到正确的.
51,153,204六角形的位置是:
在我们进行计算之前,让我们定义一下色调是什么.
色调大致是向量与投影中的点的角度,红色为0°.
......色调是六角形边缘的重点所在.
这是HSL和HSV wiki页面的计算结果.我们将在这个解释中使用它.
检查六边形及其上的位置51,153,204.
首先,我们缩放R,G,B值以填充[0,1]区间.
R = R / 255 R = 51 / 255 = 0.2
G = G / 255 G = 153 / 255 = 0.6
B = B / 255 B = 204 / 255 = 0.8
Run Code Online (Sandbox Code Playgroud)
接下来,找到max和的min值R, G, B
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
Run Code Online (Sandbox Code Playgroud)
然后,计算C(色度).色度定义为:
...色度大致是点与原点的距离.
色度是通过点的六边形的相对大小......
C = OP / OP'
C = M - m
C = 0.8- 0.2 = 0.6
Run Code Online (Sandbox Code Playgroud)
现在,我们有R,G,B,和C值.如果我们检查条件,则if M = B返回true 51,153,204.所以,我们将使用H'= (R - G) / C + 4.
我们再来检查一下六边形.(R - G) / C给出了BP段的长度.
segment = (R - G) / C = (0.2 - 0.6) / 0.6 = -0.6666666666666666
Run Code Online (Sandbox Code Playgroud)
我们将这段放在内六角上.六边形的起点是0°处的R(红色).如果段长度为正,则应为on RY,如果为负,则应为on RM.在这种情况下,它是负面的-0.6666666666666666,并且在RM边缘.
接下来,我们需要移动段的位置,或者更P?确切地说是B(因为M = B).蓝色在240°.Hexagon有6个侧面.每一面对应60°.240 / 60 = 4.我们需要移动(递增)P?by 4(240°).转移之后,P?将会在P,我们将得到的长度RYGCP.
segment = (R - G) / C = (0.2 - 0.6) / 0.6 = -0.6666666666666666
RYGCP = segment + 4 = 3.3333333333333335
Run Code Online (Sandbox Code Playgroud)
六边形的周长6对应于360°.53,151,204的距离0°是3.3333333333333335.如果我们乘3.3333333333333335用60,我们会得到它的度的位置.
H' = 3.3333333333333335
H = H' * 60 = 200°
Run Code Online (Sandbox Code Playgroud)
在这种情况下if M = R,由于我们将段的一端放在R(0°)处,如果段长度为正,我们不需要将段移动到R. 这个立场P?是积极的.但是如果段长度为负,我们需要将其移动6,因为负值意味着角位置大于180°并且我们需要进行完整旋转.
因此,荷兰维基解决方案hue = (g - b) / c;和Eng维基解决方案都不hue = ((g - b) / c) % 6;适用于负片段长度.只有SO答案hue = (g - b) / c + (g < b ? 6 : 0);适用于负值和正值.
JSFiddle:测试rgb的所有三种方法(255,71,99)
JSFiddle:在RGB Cube和色调六边形中直观地找到颜色的位置
工作色调计算:
console.log(rgb2hue(51,153,204));
console.log(rgb2hue(255,71,99));
console.log(rgb2hue(255,0,0));
console.log(rgb2hue(255,128,0));
console.log(rgb2hue(124,252,0));
function rgb2hue(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var c = max - min;
var hue;
if (c == 0) {
hue = 0;
} else {
switch(max) {
case r:
var segment = (g - b) / c;
var shift = 0 / 60; // R° / (360° / hex sides)
if (segment < 0) { // hue > 180, full rotation
shift = 360 / 60; // R° / (360° / hex sides)
}
hue = segment + shift;
break;
case g:
var segment = (b - r) / c;
var shift = 120 / 60; // G° / (360° / hex sides)
hue = segment + shift;
break;
case b:
var segment = (r - g) / c;
var shift = 240 / 60; // B° / (360° / hex sides)
hue = segment + shift;
break;
}
}
return hue * 60; // hue is in [0,6], scale it up
}Run Code Online (Sandbox Code Playgroud)
Cra*_*lot 10
该页面提供了颜色空间之间转换的功能,包括RGB到HSL。
\nfunction RGBToHSL(r,g,b) {\n // Make r, g, and b fractions of 1\n r /= 255;\n g /= 255;\n b /= 255;\n\n // Find greatest and smallest channel values\n let cmin = Math.min(r,g,b),\n cmax = Math.max(r,g,b),\n delta = cmax - cmin,\n h = 0,\n s = 0,\n l = 0;\n\n // Calculate hue\n // No difference\n if (delta === 0)\n h = 0;\n // Red is max\n else if (cmax === r)\n h = ((g - b) / delta) % 6;\n // Green is max\n else if (cmax === g)\n h = (b - r) / delta + 2;\n // Blue is max\n else\n h = (r - g) / delta + 4;\n\n h = Math.round(h * 60);\n \n // Make negative hues positive behind 360\xc2\xb0\n if (h < 0)\n h += 360;\n\n // Calculate lightness\n l = (cmax + cmin) / 2;\n\n // Calculate saturation\n s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));\n \n // Multiply l and s by 100\n s = +(s * 100).toFixed(1);\n l = +(l * 100).toFixed(1);\n\n return "hsl(" + h + "," + s + "%," + l + "%)";\n}\nRun Code Online (Sandbox Code Playgroud)\n