Colors RGB到HSL转换
我正在创建一个颜色选择器工具,对于HSL滑块,我需要能够将RGB转换为HSL。当我寻找转换的方法时,我发现了这个问题 虽然它提供了一个从RGB到HSL转换的函数,但我看不到对计算中真正发生的事情的解释。为了更好地理解它,我读了维基百科上的 稍后,我使用“HSL和HSV”页面中的计算重写了“HSL到RGB颜色转换”的函数 如果R是最大值,我就无法计算色调。参见“HSL和HSV”页面中的计算: 这是另一个荷兰语的: 这是从“HSL到RGB颜色转换”:Colors RGB到HSL转换,colors,converter,rgb,hsl,Colors,Converter,Rgb,Hsl,我正在创建一个颜色选择器工具,对于HSL滑块,我需要能够将RGB转换为HSL。当我寻找转换的方法时,我发现了这个问题 虽然它提供了一个从RGB到HSL转换的函数,但我看不到对计算中真正发生的事情的解释。为了更好地理解它,我读了维基百科上的 稍后,我使用“HSL和HSV”页面中的计算重写了“HSL到RGB颜色转换”的函数 如果R是最大值,我就无法计算色调。参见“HSL和HSV”页面中的计算: 这是另一个荷兰语的: 这是从“HSL到RGB颜色转换”: 案例r:h=(g-b)/d+(g
案例r:h=(g-b)/d+(g
我用几个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
色调=(g-b)/c;//荷兰维基
色调=((g-b)/c)%6;//英语维基
色调=(g-b)/c+(g
功能rgb2hsl(r、g、b){
//看https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation
//将r,g,b[0255]范围转换为[0,1]
r=r/255,
g=g/255,
b=b/255;
//求r,g,b的最小值和最大值
var max=数学最大值(r,g,b);
var min=数学min(r,g,b);
//亮度是最大和最小颜色分量的平均值
变量lum=(最大+最小)/2;
色变;
var-sat;
如果(max==min){//无饱和
色调=0;
sat=0;
}否则{
var c=max-min;//色度
//饱和度只是按比例缩放以填充的色度
//色调和亮度的每种组合的间隔[0,1]
sat=c/(1-数学绝对值(2*lum-1));
开关(最大值){
案例r:
//色调=(g-b)/c;
//色调=((g-b)/c)%6;
//色调=(g-b)/c+(g
继续我的评论,英文版看起来是正确的,但我不确定荷兰语版中发生了什么,因为我不理解WIKI页面
下面是我从英文WIKI页面制作的ES6版本,以及一些与WIKI示例匹配的示例数据(给出或接受Javascript的数字精度)。希望它在创建自己的函数时有用
//请参见:https://en.wikipedia.org/wiki/RGB_color_model
//见:https://en.wikipedia.org/wiki/HSL_and_HSV
//期望R、G、B、Cmax和色度在数字区间[0,1]
//如果色度为0或数字间隔[0,360]度,则返回未定义
功能色调(R、G、B、Cmax、色度){
让H;
如果(色度===0){
返回H;
}
如果(Cmax==R){
H=((G-B)/色度)%6;
}否则如果(Cmax==G){
H=((B-R)/色度)+2;
}否则如果(Cmax==B){
H=((R-G)/色度)+4;
}
H*=60;
返回H<0?H+360:H;
}
//返回提供的数字参数的平均值
函数平均值(…theArgs){
返回args.length?args.reduce((p,c)=>p+c,0)/args.length:0;
}
//期望R、G、B、Cmin、Cmax和色度在数字区间[0,1]
//类型默认为“双六角锥”公式
//为备选方案设置“luma601”或“luma709”
//见:https://en.wikipedia.org/wiki/Luma_(视频)
//返回一个数字间隔[0,1]
函数亮度(R、G、B、Cmin、Cmax,类型=‘双六角锥’){
如果(类型=='luma601'){
回报率(0.299*R)+(0.587*G)+(0.114*B);
}
如果(类型=='luma709'){
返回(0.2126*R)+(0.7152*G)+(0.0772*B);
}
返回平均值(Cmin,Cmax);
}
//期望L和色度在数字间隔[0,1]内
//返回一个数字间隔[0,1]
功能饱和度(L,色度){
返回色度===0?0:chroma/(1-Math.abs(2*L-1));
}
//将值返回到固定位数
函数toFixed(值、数字){
返回Number.isFinite(value)和&Number.isFinite(digits)?value.toFixed(digits):值;
}
//期望R、G和B在数字间隔[0,1]内
//以适当的间隔和数字返回H、S和L的映射
函数RGB2HSL(R、G、B、fixed=true){
常数Cmin=数学最小值(R,G,B);
常数Cmax=数学最大值(R,G,B);
常数色度=Cmax-Cmin;
//默认的“双六角锥”方程
常数L=亮度(R、G、B、Cmin、Cmax);
//H,以度为单位间隔[0,360]
//区间[0,1]中的L和S
返回新地图([
['H',固定(色调(R、G、B、Cmax、色度),固定和&1)],
['S',toFixed(饱和度(L,色度),固定和&3)],
['L',固定(L,固定和&3)]
]);
}
//期望值为间隔[0,255]中的数字
//以数字间隔[0,1]的形式返回标准化值
函数颜色范围(值){
返回值/255;
};
//期望R、G和B在数字间隔[0255]内
功能RGBdec2HSL(R、G、B){
返回RGB2HSL(颜色范围(R)、颜色范围(G)、颜色范围(B));
}
//将十六进制字符串转换为十进制数
函数hex2dec(值){
返回parseInt(值,16);
}
//将字符串切分为成对字符的数组
函数pairSlicer(值){
返回值.match(/../g);
}
//将“0”前置到字符串的开头,并指定长度
函数prePad(值、计数){
返回('0')。重复(计数)+值。切片(-计数);
}
//从值格式化十六进制对字符串
函数十六进制对(值){
返回hex2dec(prePad(值,2));
}
//期望R、G和B为十六进制字符串
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];
}
R = R / 255 R = 51 / 255 = 0.2
G = G / 255 G = 153 / 255 = 0.6
B = B / 255 B = 204 / 255 = 0.8
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 = OP / OP'
C = M - m
C = 0.8- 0.2 = 0.6
segment = (R - G) / C = (0.2 - 0.6) / 0.6 = -0.6666666666666666
segment = (R - G) / C = (0.2 - 0.6) / 0.6 = -0.6666666666666666
RYGCP = segment + 4 = 3.3333333333333335
H' = 3.3333333333333335
H = H' * 60 = 200°
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 + "%)";
}