gpt4 book ai didi

colors - RGB 到 HSL 的转换

转载 作者:行者123 更新时间:2023-12-03 10:31:31 25 4
gpt4 key购买 nike

我正在创建一个拾色器工具,对于 HSL 滑块,我需要能够将 RGB 转换为 HSL。当我搜索 SO 进行转换的方法时,我发现了这个问题 HSL to RGB color conversion .

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

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

如果 R 是最大值,我就会陷入色调的计算。请参阅“HSL 和 HSV”页面中的计算:

enter image description here

这是来自另一个 wiki page那是荷兰语:

enter image description here

这是来自 answers到“HSL 到 RGB 颜色转换”:

case r: h = (g - b) / d + (g < b ? 6 : 0); break; // d = max-min = c

我已经用几个 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
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];
}

最佳答案

我一直在阅读几个 wiki 页面并检查不同的计算,并在六边形上创建 RGB 立方体投影的可视化。我想发表我对这种转换的理解。因为我发现这种转换(使用几何形状的颜色模型表示)很有趣,所以我会尽量做到彻底。首先,让我们从RGB开始。

RGB

嗯,这真的不需要太多解释。在最简单的形式中,您有 3 个值,R、G 和 B,其范围为 [0,255]。例如,51,153,204 .我们可以使用条形图来表示它:

RGB Bar Graph

RGB立方体

我们还可以在 3D 空间中表示一种颜色。我们有三个值 R , G , B对应于 X , Y , 和 Z .所有三个值都在 [0,255] 中范围,结果是一个立方体。但在创建 RGB 立方体之前,让我们先处理 2D 空间。 R、G、B 的两种组合为我们提供:RG、RB、GB。如果我们在平面上绘制这些图形,我们会得到以下结果:

RGB 2D Graphs

这些是 RGB 立方体的前三个面。如果我们将它们放置在 3D 空间中,则会产生一个半立方体:

RGB Cube Sides

如果您查看上图,通过混合两种颜色,我们会在 (255,255) 处获得一种新颜色,它们是黄色、洋红色和青色。同样,这些的两个组合给了我们:YM、YC 和 MC。这些是立方体的缺失面。一旦我们添加它们,我们就会得到一个完整的立方体:

RGB Cube

以及51,153,204的位置在这个立方体中:

RGB Cube Color Position

RGB Cube 投影到六边形上

现在我们有了 RGB 立方体,让我们把它投影到一个六边形上。首先,我们将立方体在 x 上倾斜 45°。 ,然后是 y 上的 35.264° .第二次倾斜后,黑色角在底部,白色角在顶部,它们都穿过z轴。

RGB Cube Tilt

正如你所看到的,当我们从顶部看立方体时,我们得到了我们想要的六边形外观和正确的色调顺序。但是我们需要把它投影到一个真正的六边形上。我们所做的是绘制一个与立方体顶 View 大小相同的六边形。六边形的所有角对应立方体的角和颜色,立方体的顶角为白色,投影到六边形的中心。黑色省略。如果我们将每种颜色映射到六边形上,我们就会得到正确的外观。

Cube to Hexagon Projection

以及51,153,204的位置在六边形上将是:

Hue Color Position

计算色调

在我们进行计算之前,让我们先定义什么是色调。

Hue is roughly the angle of the vector to a point in the projection, with red at 0°.



... hue is how far around that hexagon’s edge the point lies.



这是来自 HSL and HSV 的计算维基页面。我们将在本说明中使用它。

Wiki calc

检查 51,153,204 的六边形和位置在上面。

Hexagon basics

首先,我们缩放 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

接下来,找到 maxmin 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

然后,计算 C (色度)。色度定义为:

... chroma is roughly the distance of the point from the origin.



Chroma is the relative size of the hexagon passing through a point ...


C = OP / OP'
C = M - m
C = 0.8- 0.2 = 0.6

现在,我们有了 R , G , B , 和 C值。如果我们检查条件, if M = B 51,153,204 返回真.所以,我们将使用 H'= (R - G) / C + 4 .

让我们再次检查六边形。 (R - G) / C给我们 BP 的长度部分。
segment = (R - G) / C = (0.2 - 0.6) / 0.6 = -0.6666666666666666

我们将把这个线段放在内六边形上。六边形的起点是 0° 处的 R(红色)。如果段长度为正,则应该在 RY ,如果为负,则应该在 RM .在这种情况下,它是负的 -0.6666666666666666 ,并在 RM 上边缘。

Segment position & shift

接下来,我们需要移动线段的位置,或者更确切地说 P₁对战 B (因为 M = B )。蓝色在 240° .六边形有6个边。每边对应 60° . 240 / 60 = 4 .我们需要移动(增加) P₁来自 4 (这是 240°)。换类后, P₁将在 P我们将得到 RYGCP 的长度.
segment = (R - G) / C = (0.2 - 0.6) / 0.6 = -0.6666666666666666
RYGCP = segment + 4 = 3.3333333333333335

六边形的周长是 6对应于 360° . 53,151,204 的距离是 3.3333333333333335 .如果我们乘以 3.3333333333333335来自 60 ,我们将得到它的位置(以度为单位)。
H' = 3.3333333333333335
H = H' * 60 = 200°

if M = R的情况下,因为我们将线段的一端放置在 R (0°),如果线段长度为正,我们不需要将线段移动到 R。 P₁的位置将是积极的。但是如果段长为负,我们需要将其移动6,因为负值意味着角位置大于180°,我们需要做一个完整的旋转。

所以,无论是荷兰维基解决方案 hue = (g - b) / c;也不是 Eng wiki 解决方案 hue = ((g - b) / c) % 6;将适用于负段长度。只有 SO 答案 hue = (g - b) / c + (g < b ? 6 : 0);适用于负值和正值。

JSFiddle: Test all three methods for rgb(255,71,99)

JSFiddle: Find a color's position in RGB Cube and hue hexagon visually

工作色调计算:

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
}

关于colors - RGB 到 HSL 的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39118528/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com