RGB to HSL conversion RGB (Red, Green, Blue) is a color model used in computer graphics and digital imaging. It represents colors by specifying the intensity of red, green, and blue components. However, sometimes it is more convenient to work with the HS
RGB to HSL conversion RGB (Red, Green, Blue) is a color model used in computer graphics and digital imaging. It represents colors by specifying the intensity of red, green, and blue components. However, sometimes it is more convenient to work with the HS
我正在创建一个色彩选择器工具,对于HSL滑块,我需要能够将RGB转换为HSL。当我在stackoverflow上搜索转换方法时,我发现了这个问题HSL to RGB color conversion。\n虽然它提供了一个从RGB到HSL的转换函数,但是对于计算过程中到底发生了什么,我看不到任何解释。为了更好地理解它,我阅读了维基百科上的HSL和HSV。\n后来,我使用了“HSL to RGB color conversion”页面上的计算方法对函数进行了重写。\n但是,当R的值最大时,我在计算色调时陷入了困境。参考“HSL and HSV”页面上的计算方法:\n\n这是一个荷兰语的维基页面上的内容:\n
\n这是关于“HSL to RGB color conversion”答案中的内容:\n
case r: h = (g - b) / d + (g < b ? 6 : 0); break; // d = max-min = c
\n我已经测试了这三种方法,并使用一些RGB值进行了比较,它们似乎产生了类似(如果不是完全相同的)结果。我想知道它们是否执行了相同的操作?对于某些特定的RGB值,我会得到不同的结果吗?我应该使用哪一个?\n
hue = (g - b) / c; // 荷兰维基 hue = ((g - b) / c) % 6; // 英文维基 hue = (g - b) / c + (g < b ? 6 : 0); // SO答案
\n
function rgb2hsl(r, g, b) { // 参考https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation // 将r,g,b [0,255]范围转换为[0,1] r = r / 255, g = g / 255, b = b / 255; // 获取r,g,b的最小值和最大值 var max = Math.max(r, g, b); var min = Math.min(r, g, b); // 亮度是最大和最小颜色分量的平均值 var lum = (max + min) / 2; var hue; var sat; if (max == min) { // 无饱和度 hue = 0; sat = 0; } else { var c = max - min; // 色度 // 饱和度简单地是色度按比例缩放填充到 // 每个色调和亮度组合的区间[0, 1] 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]; }
RGB到HSL转换的问题是由于HSL中的色调(Hue)类似于圆中的角度。相关的角度值位于0到360之间的区间。然而,计算过程中可能会出现负值。这就是为什么这三个公式是不同的原因。它们最终完成的工作是一样的,只是对0到360之间的值的处理方式不同。或者更准确地说,对于0到6之间的区间处理,然后最终乘以60得到0到360之间的值。
hue = (g - b) / c; // 来自荷兰维基百科
对于负值没有任何处理,并假设后续代码可以处理负的H值。
hue = ((g - b) / c) % 6; // 来自英文维基百科
使用%
操作符将值限制在0到6之间的区间内。
hue = (g - b) / c + (g < b ? 6 : 0); // 来自Stack Overflow的答案
通过添加+6来处理负值,使其变为正值。
你可以看到,这些只是表面上的差异。第二个或第三个公式都可以正常工作。
我不认为第二个公式对于正负值都适用。我没有看到任何情况下(g - b) / c)
大于6。它应该始终小于等于1。所以求模运算似乎是多余的。只有第三个公式按预期工作。请参考我的更新答案。
mod
对于被除数为负值的情况,通过加上除数使其变为正值。这与第三个公式完全相同。
请参考这个jsfiddle。en_rgb2hue()
使用了求模计算。它没有给出正确的值。
我的错误。对于%
操作符如何处理负值,显然有两种不同的观点。感谢你纠正我。
RGB to HSL conversion这个问题的出现原因是代码中的第3、4和5行将RGB的值除以255,目的是将RGB值缩放到0到1的范围内,而不是计算1的分数。
解决方法是将代码中的第3、4和5行修改为将RGB值除以255,以计算出1的分数。
修改后的代码如下所示:
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 + "%)"; }
这样修改后的代码就能正确地将RGB转换为HSL了。
RGB to HSL转换问题的出现原因是作者对这个转换过程有兴趣,并且想要深入理解。他通过阅读多个维基页面,检查不同的计算方法,并创建RGB立方体投影到六边形的可视化图像来解决这个问题。
RGB表示的是颜色模型中的红色(R)、绿色(G)和蓝色(B)的三个值,取值范围为0到255。作者通过条形图和立方体图形来表示RGB。
作者接下来介绍了RGB立方体的概念,通过将RGB的三个值对应到三维坐标系的X、Y和Z轴上,形成一个立方体。作者还展示了在二维平面上绘制RGB的不同组合得到的图形。
通过将这些图形放置在三维空间中,可以得到一个完整的立方体。作者还展示了通过混合两种颜色来得到新颜色的过程,并将这些颜色添加到立方体上,形成一个完整的立方体。
接下来,作者将RGB立方体投影到一个六边形上。作者先将立方体在X轴上倾斜45°,然后在Y轴上倾斜35.264°。通过这个投影,可以得到一个具有正确颜色顺序的六边形。作者解释了如何将立方体的顶部视图映射到一个真实的六边形上,并展示了在六边形上标记每个颜色的位置。
最后,作者解释了如何计算Hue(色相)。作者提供了从RGB转换到HSL的计算公式,并通过一个例子进行了详细的说明。
通过这篇文章,读者可以了解RGB到HSL转换的原因和解决方法。作者通过详细的图像和计算过程,清晰地解释了这个转换过程,并提供了可视化的示例帮助读者理解。