/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param {number} h The hue
* @param {number} s The saturation
* @param {number} l The lightness
* @return {Array} The RGB representation
*/function hslToRgb(h, s, l){var r, g, b;if(s ==0){
r = g = b = l;// achromatic}else{var hue2rgb =function hue2rgb(p, q, t){if(t <0) t +=1;if(t >1) t -=1;if(t <1/6)return p +(q - p)*6* t;if(t <1/2)return q;if(t <2/3)return p +(q - p)*(2/3- t)*6;return p;}var q = l <0.5? l *(1+ s): l + s - l * s;var p =2* l - q;
r = hue2rgb(p, q, h +1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h -1/3);}return[Math.round(r *255),Math.round(g *255),Math.round(b *255)];}
RGB para HSL:
/**
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h, s, and l in the set [0, 1].
*
* @param {number} r The red color value
* @param {number} g The green color value
* @param {number} b The blue color value
* @return {Array} The HSL representation
*/function rgbToHsl(r, g, b){
r /=255, g /=255, b /=255;var max =Math.max(r, g, b), min =Math.min(r, g, b);var h, s, l =(max + min)/2;if(max == min){
h = s =0;// achromatic}else{var d = max - min;
s = l >0.5? d /(2- max - min): d /(max + min);switch(max){case r: h =(g - b)/ d +(g < b ?6:0);break;case g: h =(b - r)/ d +2;break;case b: h =(r - g)/ d +4;break;}
h /=6;}return[h, s, l];}
Eu amo como os comentários me dizem o intervalo das variáveis e o que esperar como saída. Tão arrumado. Obrigado!
Gleno
9
Estou tentando usar isso para um projeto, mas meus resultados estão saindo apenas em escala de cinza. Isso é uma limitação do HSL <-> RGB? O artigo da wikipedia parece sugerir que apenas um único valor é definido para todos os três canais.
Bill
10
Gostaria de salientar que o uso Math.roundintroduz pequenas imprecisões nas extremidades baixa e alta (valores de 0 e 255) da escala. Os valores que não estão nas extremidades do intervalo podem arredondar para cima ou para baixo para atingir seu valor, mas os valores podem ser arredondados apenas para 0 ou 255. Isso significa que o intervalo de valores que mapeia para 0 e 255 é exatamente metade desses valores para outros valores. Para corrigir isso, use esta fórmula em vez disso: min(floor(val*256),255). Isso torna o mapeamento quase perfeito.
marcus erronius
13
Além disso, se você estiver obtendo valores em escala de cinza, provavelmente é por causa das linhas que usam h + 1/3e h - 1/3. Em muitos idiomas, isso usa divisão inteira, onde 1/3é zero. para obter resultados corretos, o uso do flutuador literais em vez disso, ie .: h + 1.0/3.0.
Não acredito que exista um módulo tão padrão no Python! Isso realmente me resgata. Eu tenho lutado com o algoritmo de conversão na entrada HSL da Wikipedia por 2 horas. Parece que o algoritmo não pode obter a saída correta.
Eu uso o brython para obter um seletor de cores no navegador, é exatamente isso que eu precisava!
EvertW
23
Implementação Java do código de Mohsen
Observe que todo o número inteiro é declarado como flutuante (ou seja, 1f) e deve ser flutuante; caso contrário, você encontrará cores cinza.
HSL para RGB
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param h The hue
* @param s The saturation
* @param l The lightness
* @return int array, the RGB representation
*/publicstaticint[] hslToRgb(float h,float s,float l){float r, g, b;if(s ==0f){
r = g = b = l;// achromatic}else{float q = l <0.5f? l *(1+ s): l + s - l * s;float p =2* l - q;
r = hueToRgb(p, q, h +1f/3f);
g = hueToRgb(p, q, h);
b = hueToRgb(p, q, h -1f/3f);}int[] rgb ={to255(r), to255(g), to255(b)};return rgb;}publicstaticint to255(float v){return(int)Math.min(255,256*v);}/** Helper method that converts hue to rgb */publicstaticfloat hueToRgb(float p,float q,float t){if(t <0f)
t +=1f;if(t >1f)
t -=1f;if(t <1f/6f)return p +(q - p)*6f* t;if(t <1f/2f)return q;if(t <2f/3f)return p +(q - p)*(2f/3f- t)*6f;return p;}
RGB para HSL
/**
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes pR, pG, and bpBare contained in the set [0, 255] and
* returns h, s, and l in the set [0, 1].
*
* @param pR The red color value
* @param pG The green color value
* @param pB The blue color value
* @return float array, the HSL representation
*/publicstaticfloat[] rgbToHsl(int pR,int pG,int pB){float r = pR /255f;float g = pG /255f;float b = pB /255f;float max =(r > g && r > b)? r :(g > b)? g : b;float min =(r < g && r < b)? r :(g < b)? g : b;float h, s, l;
l =(max + min)/2.0f;if(max == min){
h = s =0.0f;}else{float d = max - min;
s =(l >0.5f)? d /(2.0f- max - min): d /(max + min);if(r > g && r > b)
h =(g - b)/ d +(g < b ?6.0f:0.0f);elseif(g > b)
h =(b - r)/ d +2.0f;else
h =(r - g)/ d +4.0f;
h /=6.0f;}float[] hsl ={h, s, l};return hsl;}
HOW TO RETURN hsl.to.rgb(h, s, l):
SELECT:
l<=0.5: PUT l*(s+1) IN m2
ELSE: PUT l+s-l*s IN m2
PUT l*2-m2 IN m1
PUT hue.to.rgb(m1, m2, h+1/3) IN r
PUT hue.to.rgb(m1, m2, h ) IN g
PUT hue.to.rgb(m1, m2, h-1/3) IN b
RETURN (r, g, b)
HOW TO RETURN hue.to.rgb(m1, m2, h):
IF h<0: PUT h+1 IN h
IF h>1: PUT h-1 IN h
IF h*6<1: RETURN m1+(m2-m1)*h*6
IF h*2<1: RETURN m2
IF h*3<2: RETURN m1+(m2-m1)*(2/3-h)*6
RETURN m1
Eu acredito que esta é a fonte para algumas das outras respostas aqui.
Aqui está o código da resposta de Mohsen em C #, se mais alguém quiser. Nota: Coloré uma classe personalizada e Vector4é do OpenTK. Ambos são fáceis de substituir por outra coisa de sua escolha.
Hsl para Rgba
/// <summary>/// Converts an HSL color value to RGB./// Input: Vector4 ( X: [0.0, 1.0], Y: [0.0, 1.0], Z: [0.0, 1.0], W: [0.0, 1.0] )/// Output: Color ( R: [0, 255], G: [0, 255], B: [0, 255], A: [0, 255] )/// </summary>/// <param name="hsl">Vector4 defining X = h, Y = s, Z = l, W = a. Ranges [0, 1.0]</param>/// <returns>RGBA Color. Ranges [0, 255]</returns>publicstaticColorHslToRgba(Vector4 hsl){float r, g, b;if(hsl.Y ==0.0f)
r = g = b = hsl.Z;else{var q = hsl.Z <0.5f? hsl.Z *(1.0f+ hsl.Y): hsl.Z + hsl.Y - hsl.Z * hsl.Y;var p =2.0f* hsl.Z - q;
r =HueToRgb(p, q, hsl.X +1.0f/3.0f);
g =HueToRgb(p, q, hsl.X);
b =HueToRgb(p, q, hsl.X -1.0f/3.0f);}returnnewColor((int)(r *255),(int)(g *255),(int)(b *255),(int)(hsl.W *255));}// Helper for HslToRgbaprivatestaticfloatHueToRgb(float p,float q,float t){if(t <0.0f) t +=1.0f;if(t >1.0f) t -=1.0f;if(t <1.0f/6.0f)return p +(q - p)*6.0f* t;if(t <1.0f/2.0f)return q;if(t <2.0f/3.0f)return p +(q - p)*(2.0f/3.0f- t)*6.0f;return p;}
Rgba para Hsl
/// <summary>/// Converts an RGB color value to HSL./// Input: Color ( R: [0, 255], G: [0, 255], B: [0, 255], A: [0, 255] )/// Output: Vector4 ( X: [0.0, 1.0], Y: [0.0, 1.0], Z: [0.0, 1.0], W: [0.0, 1.0] )/// </summary>/// <param name="rgba"></param>/// <returns></returns>publicstaticVector4RgbaToHsl(Color rgba){float r = rgba.R /255.0f;float g = rgba.G /255.0f;float b = rgba.B /255.0f;float max =(r > g && r > b)? r :(g > b)? g : b;float min =(r < g && r < b)? r :(g < b)? g : b;float h, s, l;
h = s = l =(max + min)/2.0f;if(max == min)
h = s =0.0f;else{float d = max - min;
s =(l >0.5f)? d /(2.0f- max - min): d /(max + min);if(r > g && r > b)
h =(g - b)/ d +(g < b ?6.0f:0.0f);elseif(g > b)
h =(b - r)/ d +2.0f;else
h =(r - g)/ d +4.0f;
h /=6.0f;}returnnewVector4(h, s, l, rgba.A /255.0f);}
Também daqui , o que explica muito bem a matemática.
Isso é basicamente um monte de funções para converter de e para HSL (Hue Saturation Lightness)
Testado e trabalhando no PHP 5.6.15
TL; DR : O código completo pode ser encontrado aqui em Pastebin .
Hex para HSL
Entrada: Cor hexadecimal no formato: [#] 0f4 ou [#] 00ff44 (sinal de libra opcional)
Saída: HSL em graus, porcentagem, porcentagem
/**
* Input: hex color
* Output: hsl(in ranges from 0-1)
*
* Takes the hex, converts it to RGB, and sends
* it to RGBToHsl. Returns the output.
*
*/function hexToHsl($hex){
$r ="";
$g ="";
$b ="";
$hex = str_replace('#','', $hex);if(strlen($hex)==3){
$r = substr($hex,0,1);
$r = $r . $r;
$g = substr($hex,1,1);
$g = $g . $g;
$b = substr($hex,2,1);
$b = $b . $b;} elseif (strlen($hex)==6){
$r = substr($hex,0,2);
$g = substr($hex,2,2);
$b = substr($hex,4,2);}else{returnfalse;}
$r = hexdec($r);
$g = hexdec($g);
$b = hexdec($b);
$hsl = rgbToHsl($r,$g,$b);return $hsl;}
RGB para HSL
Entrada: RGB no intervalo 0-255 Saída: HSL em graus, porcentagem, porcentagem.
/**
*
*Credits:
* /programming/4793729/rgb-to-hsl-and-back-calculation-problems
* http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/
*
* Called by hexToHsl by default.
*
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/.
* Assumes r, g, and b are contained in the range [0 - 255] and
* returns h, s, and l in the format Degrees, Percent, Percent.
*
* @param Number r The red color value
* @param Number g The green color value
* @param Number b The blue color value
* @return Array The HSL representation
*/function rgbToHsl($r, $g, $b){//For the calculation, rgb needs to be in the range from 0 to 1. To convert, divide by 255 (ff).
$r /=255;
$g /=255;
$b /=255;
$myMax = max($r, $g, $b);
$myMin = min($r, $g, $b);
$maxAdd =($myMax + $myMin);
$maxSub =($myMax - $myMin);//luminence is (max + min)/2
$h =0;
$s =0;
$l =($maxAdd /2.0);//if all the numbers are equal, there is no saturation (greyscale).if($myMin != $myMax){if($l <0.5){
$s =($maxSub / $maxAdd);}else{
$s =(2.0- $myMax - $myMin);//note order of opperations - can't use $maxSub here
$s =($maxSub / $s);}//find hueswitch($myMax){case $r:
$h =($g - $b);
$h =($h / $maxSub);break;case $g:
$h =($b - $r);
$h =($h / $maxSub);
$h =($h +2.0);break;case $b:
$h =($r - $g);
$h =($h / $maxSub);
$h =($h +4.0);break;}}
$hsl = hslToDegPercPerc($h, $s, $l);return $hsl;}
HSL (intervalo de 0 a 1) para graus, porcentagem, formato percentual
Para os cálculos matemáticos, o HSL é mais fácil de lidar no intervalo de 0 a 1, mas para a legibilidade humana, é mais fácil em graus, porcentagem, porcentagem. Essa função pega HSL nos intervalos de 0 a 1 e retorna HSL em graus, porcentagem, porcentagem.
/**
* Input: HSL in ranges 0-1.
* Output: HSL in format Deg, Perc, Perc.
*
* Note: rgbToHsl calls this function by default.
*
* Multiplies $h by 60, and $s and $l by 100.
*/function hslToDegPercPerc($h, $s, $l){//convert h to degrees
$h *=60;if($h <0){
$h +=360;}//convert s and l to percentage
$s *=100;
$l *=100;
$hsl['h']= $h;
$hsl['s']= $s;
$hsl['l']= $l;return $hsl;}
HSL (graus, porcentagem, formato percentual) a HSL no intervalo de 0 a 1
Essa função converte HSL no formato Graus, Porcentagem, Porcentagem nos intervalos de 0 a 1 para facilitar a computação.
/**
* Input: HSL in format Deg, Perc, Perc
* Output: An array containing HSL in ranges 0-1
*
* Divides $h by 60, and $s and $l by 100.
*
* hslToRgb calls this by default.
*/function degPercPercToHsl($h, $s, $l){//convert h, s, and l back to the 0-1 range//convert the hue's 360 degrees in a circle to 1
$h /=360;//convert the saturation and lightness to the 0-1 //range by multiplying by 100
$s /=100;
$l /=100;
$hsl['h']= $h;
$hsl['s']= $s;
$hsl['l']= $l;return $hsl;}
HSL para RGB
Entrada: HSL no formato Graus, Porcentagem, Porcentagem Saída: RGB no formato 255, 255, 255.
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/.
* Assumes h, s, and l are in the format Degrees,
* Percent, Percent, and returns r, g, and b in
* the range [0 - 255].
*
* Called by hslToHex by default.
*
* Calls:
* degPercPercToHsl
* hueToRgb
*
* @param Number h The hue value
* @param Number s The saturation level
* @param Number l The luminence
* @return Array The RGB representation
*/function hslToRgb($h, $s, $l){
$hsl = degPercPercToHsl($h, $s, $l);
$h = $hsl['h'];
$s = $hsl['s'];
$l = $hsl['l'];//If there's no saturation, the color is a greyscale,//so all three RGB values can be set to the lightness.//(Hue doesn't matter, because it's grey, not color)if($s ==0){
$r = $l *255;
$g = $l *255;
$b = $l *255;}else{//calculate some temperary variables to make the //calculation eaisier.if($l <0.5){
$temp2 = $l *(1+ $s);}else{
$temp2 =($l + $s)-($s * $l);}
$temp1 =2* $l - $temp2;//run the calculated vars through hueToRgb to//calculate the RGB value. Note that for the Red//value, we add a third (120 degrees), to adjust //the hue to the correct section of the circle for//red. Simalarly, for blue, we subtract 1/3.
$r =255* hueToRgb($temp1, $temp2, $h +(1/3));
$g =255* hueToRgb($temp1, $temp2, $h);
$b =255* hueToRgb($temp1, $temp2, $h -(1/3));}
$rgb['r']= $r;
$rgb['g']= $g;
$rgb['b']= $b;return $rgb;}
Matiz para RGB
Essa função é chamada por hslToRgb para converter o matiz em valores RGB separados.
/**
* Converts an HSL hue to it's RGB value.
*
* Input: $temp1 and $temp2 - temperary vars based on
* whether the lumanence is less than 0.5, and
* calculated using the saturation and luminence
* values.
* $hue - the hue (to be converted to an RGB
* value) For red, add 1/3 to the hue, green
* leave it alone, and blue you subtract 1/3
* from the hue.
*
* Output: One RGB value.
*
* Thanks to Easy RGB for this function (Hue_2_RGB).
* http://www.easyrgb.com/index.php?X=MATH&$h=19#text19
*
*/function hueToRgb($temp1, $temp2, $hue){if($hue <0){
$hue +=1;}if($hue >1){
$hue -=1;}if((6* $hue)<1){return($temp1 +($temp2 - $temp1)*6* $hue);} elseif ((2* $hue)<1){return $temp2;} elseif ((3* $hue)<2){return($temp1 +($temp2 - $temp1)*((2/3)- $hue)*6);}return $temp1;}
HSL para Hex
Entrada: HSL no formato Graus, Porcentagem, Porcentagem Saída: Hex no formato 00ff22(sem sinal de libra).
Converte em RGB, depois converte separadamente em hexadecimal.
/**
* Converts HSL to Hex by converting it to
* RGB, then converting that to hex.
*
* string hslToHex($h, $s, $l[, $prependPound = true]
*
* $h is the Degrees value of the Hue
* $s is the Percentage value of the Saturation
* $l is the Percentage value of the Lightness
* $prependPound is a bool, whether you want a pound
* sign prepended. (optional - default=true)
*
* Calls:
* hslToRgb
*
* Output: Hex in the format: #00ff88 (with
* pound sign). Rounded to the nearest whole
* number.
*/function hslToHex($h, $s, $l, $prependPound =true){//convert hsl to rgb
$rgb = hslToRgb($h,$s,$l);//convert rgb to hex
$hexR = $rgb['r'];
$hexG = $rgb['g'];
$hexB = $rgb['b'];//round to the nearest whole number
$hexR = round($hexR);
$hexG = round($hexG);
$hexB = round($hexB);//convert to hex
$hexR = dechex($hexR);
$hexG = dechex($hexG);
$hexB = dechex($hexB);//check for a non-two string length//if it's 1, we can just prepend a//0, but if it is anything else non-2,//it must return false, as we don't //know what format it is in.if(strlen($hexR)!=2){if(strlen($hexR)==1){//probably in format #0f4, etc.
$hexR ="0". $hexR;}else{//unknown formatreturnfalse;}}if(strlen($hexG)!=2){if(strlen($hexG)==1){
$hexG ="0". $hexG;}else{returnfalse;}}if(strlen($hexB)!=2){if(strlen($hexB)==1){
$hexB ="0". $hexB;}else{returnfalse;}}//if prependPound is set, will prepend a//# sign to the beginning of the hex code.//(default = true)
$hex ="";if($prependPound){
$hex ="#";}
$hex = $hex . $hexR . $hexG . $hexB;return $hex;}
Eu fiz uma edição para rgbToHsl, você pode querer atualizar seu código php. Houve / há um bug no código. Em rgbToHsl () s = maxSub / (2 - maxSub)deve sers = maxSub / (2 - maxAdd)
Lex
@ Lex De acordo com aqui e aqui , meu código está realmente correto. Eu acho que você pode estar confundindo o if l < 0.5com o else. Você poderia explicar seu pensamento? Obrigado por reservar um tempo para dar feedback!
Cullub
1
desculpe, você está certo, mas ainda há um problema de ordem de operações. # 8cd08c para HSL usando este cálculo (2 - maxSub) = 1.7333333333333334quando deveria ser como no segundo exemplo de link ( 2 - max - min ) = 0.6352941176470588. Usar 2 - maxAddme aproximou consistentemente da saída do photoshops, por isso presumi que estivesse correto.
Lex
Ah ok. Obrigado por apontar isso! Eu consertei agora. Espero que isso seja útil!
Essa deve ser a resposta aceita ... muito mais simples e mais intuitiva! Você pode reverter o algoritmo?
JoelFan #
@ JoelFan - É simples, mas não está correto . Há nenhuma maneira para expressões racionais puros (com apenas +, -, *, e /) - como são usadas, por definição, para as conversões de cores - para expressá-los com a ajuda das sinefunções com variáveis da mesma independente (entrada). Apesar disso, é bom entender o princípio (mas não realizar conversões).
MarianD
O problema com esta solução é que MÉDIA é sempre igual a ZERO: (R1 + G1 + B1) = L*[ SIN(H) + SIN(H+120) + SIN(H+240) ]- e agora, se usarmos a fórmula sin(a)+sin(b) = 2*sin((a+b)/2)*cos((a-b)/2)para os dois primeiros pecados, obtemos: AVERAGE=L*( sin(h+60) + sin(h+240) )e novamente AVERAGE= L*2*sin(h+150)*cos(-180/2) = 0(desde cos (-180/2) = cos (90) = 0). Portanto, o cálculo da saturação está errado e, de fato, a saturação funciona aqui como luminância.
Kamil Kiełczewski
@JoelFan O segundo problema com esta solução é que precisamos adicionar 180 graus a H para ter uma versão "compatível" com en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB (caso de teste: cor vermelha para H = 0), mas também ainda há problema com o número de cores - na solução acima, as cores amarela, magenta e ciano são omitidas e / ou mapeadas de maneira incorreta. Há fiddle js com comparação: jsfiddle.net/Lamik/9s24uc1o/10
Kamil Kiełczewski
3
Aqui está uma versão rápida, super simples e sem ramificação no GLSL:
Aqui está a função javascript modificada, que gera Hue no conjunto de 0 a 360 graus.
function rgbToHsl(r, g, b){
r /=255, g /=255, b /=255;var max =Math.max(r, g, b), min =Math.min(r, g, b);var h, s, l =(max + min)/2;if(max == min){
h = s =0;// achromatic}else{var d = max - min;
s = l >0.5? d /(2- max - min): d /(max + min);switch(max){case r: h =(g - b)/ d ;break;case g: h =2+((b - r)/ d);break;case b: h =4+((r - g)/ d);break;}
h*=60;if(h <0) h +=360;}return([h, s, l]);}
alert(rgbToHsl(125,115,145));
Eu peguei isso do HSL Picker de Brandon Mathis código fonte .
Foi originalmente escrito em CoffeeScript . Eu o convertei para JavaScript usando um conversor online e removi o mecanismo para verificar se a entrada do usuário era um valor RGB válido. Esta resposta funcionou para o meu caso de usuário, como a resposta mais votada nesta postagem que achei que não produzia um valor HSL válido.
Observe que ele retorna um hslavalor, com arepresentação de opacidade / transparência. 0é completamente transparente e 1totalmente opaco.
function rgbToHsl(rgb){var a,add, b, diff, g, h, hue, l, lum, max, min, r, s, sat;
r = parseFloat(rgb[0])/255;
g = parseFloat(rgb[1])/255;
b = parseFloat(rgb[2])/255;
max =Math.max(r, g, b);
min =Math.min(r, g, b);
diff = max - min;add= max + min;
hue = min === max ?0: r === max ?((60*(g - b)/ diff)+360)%360: g === max ?(60*(b - r)/ diff)+120:(60*(r - g)/ diff)+240;
lum =0.5*add;
sat = lum ===0?0: lum ===1?1: lum <=0.5? diff /add: diff /(2-add);
h =Math.round(hue);
s =Math.round(sat *100);
l =Math.round(lum *100);
a = parseFloat(rgb[3])||1;return[h, s, l, a];}
Eu usei isso como base para um método Python. Obrigado.
JayJay123
isso não é HSL para RGB, como pede o cartaz
bryc
1
Para quando você precisar de RGB para HSV e vice-versa:
function rgbToHsv(r, g, b){
r /=255, g /=255, b /=255;var min =Math.min(r, g, b),
max =Math.max(r, g, b),
delta = max - min,
h =0, s =0, v = max;if(min != max){
s =(delta / max);switch(max){case r: h =(g - b)/ delta +(g < b ?6:0);break;case g: h =(b - r)/ delta +2;break;case b: h =(r - g)/ delta +4;break;}
h /=6;}return[h, s, v];}function hsvToRgb(h, s, v){var step = h /(1/6),
pos = step -Math.floor(step),// the hue position within the current step
m =(Math.floor(step)%2)?(1- pos)* v : pos * v,// mix color value adjusted to the brightness(v)
max =1* v,
min =(1- s)* v,
med = m +((1- s)*(v - m)),
r, g, b;switch(Math.floor(step)){case0:
r = max;
g = med;
b = min;break;case1:
r = med;
g = max;
b = min;break;case2:
r = min;
g = max;
b = med;break;case3:
r = min;
g = med;
b = max;break;case4:
r = med;
g = min;
b = max;break;case5:
r = max;
g = min;
b = med;break;}return[Math.round(r *255),Math.round(g *255),Math.round(b *255)];}
Aqui está o código da resposta de Mohsen em C # direcionado especificamente para o Unity3D. Foi adaptado da resposta em C # dada por Alec Thilenius acima.
usingUnityEngine;usingSystem.Collections;publicclassColorTools{/// <summary>/// Converts an HSL color value to RGB./// Input: Vector4 ( X: [0.0, 1.0], Y: [0.0, 1.0], Z: [0.0, 1.0], W: [0.0, 1.0] )**strong text**/// Output: Color ( R: [0.0, 1.0], G: [0.0, 1.0], B: [0.0, 1.0], A: [0.0, 1.0] )/// </summary>/// <param name="hsl">Vector4 defining X = h, Y = s, Z = l, W = a. Ranges [0, 1.0]</param>/// <returns>RGBA Color. Ranges [0.0, 1.0]</returns>publicstaticColorHslToRgba(Vector4 hsl){float r, g, b;if(hsl.y ==0.0f)
r = g = b = hsl.z;else{var q = hsl.z <0.5f? hsl.z *(1.0f+ hsl.y): hsl.z + hsl.y - hsl.z * hsl.y;var p =2.0f* hsl.z - q;
r =HueToRgb(p, q, hsl.x +1.0f/3.0f);
g =HueToRgb(p, q, hsl.x);
b =HueToRgb(p, q, hsl.x -1.0f/3.0f);}returnnewColor(r, g, b, hsl.w);}// Helper for HslToRgbaprivatestaticfloatHueToRgb(float p,float q,float t){if(t <0.0f) t +=1.0f;if(t >1.0f) t -=1.0f;if(t <1.0f/6.0f)return p +(q - p)*6.0f* t;if(t <1.0f/2.0f)return q;if(t <2.0f/3.0f)return p +(q - p)*(2.0f/3.0f- t)*6.0f;return p;}/// <summary>/// Converts an RGB color value to HSL./// Input: Color ( R: [0.0, 1.0], G: [0.0, 1.0], B: [0.0, 1.0], A: [0.0, 1.0] )/// Output: Vector4 ( X: [0.0, 1.0], Y: [0.0, 1.0], Z: [0.0, 1.0], W: [0.0, 1.0] )/// </summary>/// <param name="rgba"></param>/// <returns></returns>publicstaticVector4RgbaToHsl(Color rgba){float max =(rgba.r > rgba.g && rgba.r > rgba.b)? rgba.r :(rgba.g > rgba.b)? rgba.g : rgba.b;float min =(rgba.r < rgba.g && rgba.r < rgba.b)? rgba.r :(rgba.g < rgba.b)? rgba.g : rgba.b;float h, s, l;
h = s = l =(max + min)/2.0f;if(max == min)
h = s =0.0f;else{float d = max - min;
s =(l >0.5f)? d /(2.0f- max - min): d /(max + min);if(rgba.r > rgba.g && rgba.r > rgba.b)
h =(rgba.g - rgba.b)/ d +(rgba.g < rgba.b ?6.0f:0.0f);elseif(rgba.g > rgba.b)
h =(rgba.b - rgba.r)/ d +2.0f;else
h =(rgba.r - rgba.g)/ d +4.0f;
h /=6.0f;}returnnewVector4(h, s, l, rgba.a);}}
Para todos que disseram que a solução Garry Tan convertendo incorreto de RGB para HSL e vice-versa. É porque ele deixou de fora parte da fração do número em seu código. Corrigi o código dele (javascript). Desculpe pelo link no idioma russo, mas no inglês ausente - HSL-wiki
function toHsl(r, g, b){
r /=255.0;
g /=255.0;
b /=255.0;var max =Math.max(r, g, b);var min =Math.min(r, g, b);var h, s, l =(max + min)/2.0;if(max == min){
h = s =0;}else{var d = max - min;
s =(l >0.5? d /(2.0- max - min): d /(max + min));if(max == r && g >= b){
h =1.0472*(g - b)/ d ;}elseif(max == r && g < b){
h =1.0472*(g - b)/ d +6.2832;}elseif(max == g){
h =1.0472*(b - r)/ d +2.0944;}elseif(max == b){
h =1.0472*(r - g)/ d +4.1888;}}return{
str:'hsl('+ parseInt(h /6.2832*360.0+0.5)+','+ parseInt(s *100.0+0.5)+'%,'+ parseInt(l *100.0+0.5)+'%)',
obj:{ h: parseInt(h /6.2832*360.0+0.5), s: parseInt(s *100.0+0.5), l: parseInt(l *100.0+0.5)}};};
Um valor hsl | a color, definido em javascript, será instantaneamente convertido em rgb | a Tudo o que você precisa fazer é acessar o valor do estilo calculado
Tecnicamente, eu acho, isso não é nem qualquer linha de código - é feito automaticamente. Portanto, dependendo do seu ambiente, você poderá se safar disso. Não que não haja muitas respostas muito atenciosas aqui. Não sei qual é o seu objetivo.
Agora, e se você quiser converter de rbg | a para hsl | a?
Implementação C ++ com desempenho provavelmente melhor que o código @Mohsen. Ele usa um intervalo [0-6] para o matiz, evitando a divisão e multiplicação por 6. O intervalo S e L é [0,1]
Please.HEX_to_HSV('#ffeb3b')
Respostas:
Garry Tan postou uma solução Javascript em seu blog (que ele atribui a um mjijackson.com agora extinto, mas está arquivado aqui e o autor original tem uma essência - graças a user2441511).
O código é publicado novamente abaixo:
HSL para RGB:
RGB para HSL:
fonte
Math.round
introduz pequenas imprecisões nas extremidades baixa e alta (valores de 0 e 255) da escala. Os valores que não estão nas extremidades do intervalo podem arredondar para cima ou para baixo para atingir seu valor, mas os valores podem ser arredondados apenas para 0 ou 255. Isso significa que o intervalo de valores que mapeia para 0 e 255 é exatamente metade desses valores para outros valores. Para corrigir isso, use esta fórmula em vez disso:min(floor(val*256),255)
. Isso torna o mapeamento quase perfeito.h + 1/3
eh - 1/3
. Em muitos idiomas, isso usa divisão inteira, onde1/3
é zero. para obter resultados corretos, o uso do flutuador literais em vez disso, ie .:h + 1.0/3.0
.Encontrou a maneira mais fácil, python para o resgate : D
fonte
Color::HSL.new(40,50,60).to_rgb
Implementação Java do código de Mohsen
Observe que todo o número inteiro é declarado como flutuante (ou seja, 1f) e deve ser flutuante; caso contrário, você encontrará cores cinza.
HSL para RGB
RGB para HSL
fonte
O artigo para HSL e HSV na wikipedia contém algumas fórmulas. Os cálculos são um pouco complicados, portanto, pode ser útil dar uma olhada nas implementações existentes .
fonte
Se você está procurando algo que definitivamente esteja em conformidade com a semântica CSS para HSL e RGB, poderá usar o algoritmo especificado na especificação CSS 3 , que diz:
Eu acredito que esta é a fonte para algumas das outras respostas aqui.
fonte
Código C # da resposta de Mohsen.
Aqui está o código da resposta de Mohsen em C #, se mais alguém quiser. Nota:
Color
é uma classe personalizada eVector4
é do OpenTK. Ambos são fáceis de substituir por outra coisa de sua escolha.Hsl para Rgba
Rgba para Hsl
fonte
Implementação PHP do código C # de Chris
Também daqui , o que explica muito bem a matemática.
Isso é basicamente um monte de funções para converter de e para HSL (Hue Saturation Lightness)
Testado e trabalhando no PHP 5.6.15
TL; DR : O código completo pode ser encontrado aqui em Pastebin .
Hex para HSL
Entrada: Cor hexadecimal no formato: [#] 0f4 ou [#] 00ff44 (sinal de libra opcional)
Saída: HSL em graus, porcentagem, porcentagem
RGB para HSL
Entrada: RGB no intervalo 0-255 Saída: HSL em graus, porcentagem, porcentagem.
HSL (intervalo de 0 a 1) para graus, porcentagem, formato percentual
Para os cálculos matemáticos, o HSL é mais fácil de lidar no intervalo de 0 a 1, mas para a legibilidade humana, é mais fácil em graus, porcentagem, porcentagem. Essa função pega HSL nos intervalos de 0 a 1 e retorna HSL em graus, porcentagem, porcentagem.
HSL (graus, porcentagem, formato percentual) a HSL no intervalo de 0 a 1
Essa função converte HSL no formato Graus, Porcentagem, Porcentagem nos intervalos de 0 a 1 para facilitar a computação.
HSL para RGB
Entrada: HSL no formato Graus, Porcentagem, Porcentagem Saída: RGB no formato
255, 255, 255
.Matiz para RGB
Essa função é chamada por hslToRgb para converter o matiz em valores RGB separados.
HSL para Hex
Entrada: HSL no formato Graus, Porcentagem, Porcentagem Saída: Hex no formato
00ff22
(sem sinal de libra).Converte em RGB, depois converte separadamente em hexadecimal.
fonte
rgbToHsl
, você pode querer atualizar seu código php. Houve / há um bug no código. Em rgbToHsl ()s = maxSub / (2 - maxSub)
deve sers = maxSub / (2 - maxAdd)
if l < 0.5
com oelse
. Você poderia explicar seu pensamento? Obrigado por reservar um tempo para dar feedback!(2 - maxSub) = 1.7333333333333334
quando deveria ser como no segundo exemplo de link( 2 - max - min ) = 0.6352941176470588
. Usar2 - maxAdd
me aproximou consistentemente da saída do photoshops, por isso presumi que estivesse correto.É assim que faço, que é fácil lembrar: pensar em RGB como três raios de uma roda, separados por 120 graus.
A parte complicada é a saturação, que é em escala reduzida à média das três.
fonte
+
,-
,*
, e/
) - como são usadas, por definição, para as conversões de cores - para expressá-los com a ajuda dassine
funções com variáveis da mesma independente (entrada). Apesar disso, é bom entender o princípio (mas não realizar conversões).(R1 + G1 + B1) = L*[ SIN(H) + SIN(H+120) + SIN(H+240) ]
- e agora, se usarmos a fórmulasin(a)+sin(b) = 2*sin((a+b)/2)*cos((a-b)/2)
para os dois primeiros pecados, obtemos:AVERAGE=L*( sin(h+60) + sin(h+240) )
e novamenteAVERAGE= L*2*sin(h+150)*cos(-180/2) = 0
(desde cos (-180/2) = cos (90) = 0). Portanto, o cálculo da saturação está errado e, de fato, a saturação funciona aqui como luminância.Aqui está uma versão rápida, super simples e sem ramificação no GLSL:
Não fica muito menor do que isso ~
Link para a prova de conceito original: https://www.shadertoy.com/view/XljGzV
(Isenção de responsabilidade: não é meu código!)
fonte
Aqui está a função javascript modificada, que gera Hue no conjunto de 0 a 360 graus.
fonte
Eu peguei isso do HSL Picker de Brandon Mathis código fonte .
Foi originalmente escrito em CoffeeScript . Eu o convertei para JavaScript usando um conversor online e removi o mecanismo para verificar se a entrada do usuário era um valor RGB válido. Esta resposta funcionou para o meu caso de usuário, como a resposta mais votada nesta postagem que achei que não produzia um valor HSL válido.
Observe que ele retorna um
hsla
valor, coma
representação de opacidade / transparência.0
é completamente transparente e1
totalmente opaco.fonte
Para quando você precisar de RGB para HSV e vice-versa:
fonte
Código Unity3D C # da resposta de Mohsen.
Aqui está o código da resposta de Mohsen em C # direcionado especificamente para o Unity3D. Foi adaptado da resposta em C # dada por Alec Thilenius acima.
fonte
Para todos que disseram que a solução Garry Tan convertendo incorreto de RGB para HSL e vice-versa. É porque ele deixou de fora parte da fração do número em seu código. Corrigi o código dele (javascript). Desculpe pelo link no idioma russo, mas no inglês ausente - HSL-wiki
fonte
Um valor hsl | a color, definido em javascript, será instantaneamente convertido em rgb | a Tudo o que você precisa fazer é acessar o valor do estilo calculado
Tecnicamente, eu acho, isso não é nem qualquer linha de código - é feito automaticamente. Portanto, dependendo do seu ambiente, você poderá se safar disso. Não que não haja muitas respostas muito atenciosas aqui. Não sei qual é o seu objetivo.
Agora, e se você quiser converter de rbg | a para hsl | a?
fonte
Implementação C ++ com desempenho provavelmente melhor que o código @Mohsen. Ele usa um intervalo [0-6] para o matiz, evitando a divisão e multiplicação por 6. O intervalo S e L é [0,1]
fonte
Com H, S e L no intervalo [0,1]:
fonte
Eu precisava de um peso realmente leve, não é 100%, mas fica perto o suficiente para alguns casos de uso.
fonte
Implementação em PHP do código do @ Mohsen (incluindo Teste!)
Desculpe postar isso novamente. Mas eu realmente não vi nenhuma outra implementação que dê a qualidade que eu precisava.
fonte