Преобразование цвета HSB/HSV в HSL
как преобразовать цвет HSB в HSL?
Photoshop показывает цвет HSB в своем палитре цветов. Цвет HSL может использоваться в CSS.
я попробовал это JS:
function hsb2hsl(h, s, b) { return { h: h, s: s, l: b-s/2 } }
но hsb2hsl(0, 100, 50).l == 0
вместо 25
обновление: могу ли я сделать это без преобразования HSB → RGB → HSL?
7 ответов
боюсь, что мои знания Javascript отсутствуют, но вы должны быть в состоянии вывести преобразование из http://ariya.blogspot.com/2008/07/converting-between-hsl-and-hsv.html
давайте представим, что на самом деле HSB(V), HSL, а как строятся:
Hue значение цвета идет из 0
to 360
градусов (где 0
красный) как для HSB, так и для HSL.
Поверх оттенка наносится это линейные градиентные слои
HSB (также известный как HSV)
- Hue
- насыщенность = (слева) Белый → прозрачный
- яркость (стоимостью) = (от дна) черный → прозрачный
HSL
- Hue
- насыщенность = (слева) серый50%(#808080, RGB128,128,128) → прозрачный
- легкость = (от дна) черный → прозрачный → Белый
давайте посмотрим, как сделать SB > SL > SB имея:
var H = 360, // Values 0-360 but we'll use red by default
SB = {s:0, b:0}, // Values 0-1
SL = {s:0, l:0}; // Values 0-1
преобразование
function sb2sl() {
SL.l = (2 - SB.s) * SB.b / 2;
SL.s = SL.l&&SL.l<1 ? SB.s*SB.b/(SL.l<0.5 ? SL.l*2 : 2-SL.l*2) : SL.s;
}
function sl2sb() {
var t = SL.s * (SL.l<0.5 ? SL.l : 1-SL.l);
SB.b = SL.l+t;
SB.s = SL.l>0 ? 2*t/SB.b : SB.s ;
}
преобразовать в non-floated %
процентов значения люблю:
(SB.s * 100 |0) // |0 removes floats
вот практическое пример:
var $SB = $("#SB"), $SBdot = $SB.find("span"), $SBres = $("#SBres"),
$SL = $("#SL"), $SLdot = $SL.find("span"), $SLres = $("#SLres"),
size = $SB.width(), // the area W,H size
SB = {s:0, b:0}, // Values 0-1
SL = {s:0, l:0}; // Values 0-1
function sb2sl() {
SL.l = (2 - SB.s) * SB.b / 2;
SL.s = SL.l&&SL.l<1 ? SB.s*SB.b/(SL.l<0.5 ? SL.l*2 : 2-SL.l*2) : SL.s;
}
function sl2sb() {
var t = SL.s * (SL.l<0.5 ? SL.l : 1-SL.l);
SB.b = SL.l+t;
SB.s = SL.l>0 ? 2*t/SB.b : SB.s ;
}
$SB.add( $SL ).on("mousemove", function(e){
var cr = this.getBoundingClientRect();
var x = e.clientX - cr.left |0;
var y = e.clientY - cr.top |0;
if(this.id==="SB") { // Mouse over #SB ?
// Mouse position to 0-1 SB values
SB.s = x / (size-1);
SB.b = 1- y / (size-1);
// Convert inally SB to SL
sb2sl();
// Move dots
$SBdot.css({left:x, top:y});
$SLdot.css({left: SL.s*size, top:size-(SL.l*size)});
}else{
// Mouse position to SL 0-1 values
SL.s = x / (size-1);
SL.l = 1- y / (size-1);
// Convert finally SL to SB
sl2sb();
// Move dots
$SLdot.css({left:x, top:y});
$SBdot.css({left: SB.s*size, top:size-(SB.b*size)});
}
// Write textual results
$SBres.html("S:"+ (SB.s*100|0) +"%<br> B:"+ (SB.b*100|0)+"%");
$SLres.html("S:"+ (SL.s*100|0) +"%<br> L:"+ (SL.l*100|0)+"%");
});
body{margin:0 20px;font:12px/1.2 sans-serif;}
body>div{display:inline-block;margin: 20px;}
#SL,
#SB{
position:relative;
width:120px; height:120px;
cursor:crosshair;
}
#SB{
background:
linear-gradient(to bottom, transparent, #000),
linear-gradient(to right, #fff, transparent),
red;
}
#SL{
background:
linear-gradient(to bottom, #fff, transparent, #000),
linear-gradient(to right, #808080, transparent),
red
}
#SL span,
#SB span{
position:absolute;
width:9px; height:9px;
margin:-4px;
border-radius:50%;
box-shadow:0 0 0 1px #fff, 0 0 0 2px #000;
pointer-events:none;
}
#SB span{left:100%; top:0;}
#SL span{left:100%; top:50%;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<b>HSB(HSV)</b>
<div id="SB"><span></span></div>
<p id="SBres">S:100%<br>B:100%</p>
</div>
<div>
<b>HSL</b>
<div id="SL"><span></span></div>
<p id="SLres">S:100%<br>L:50%</p>
</div>
Я думаю, что это самое точное:
function hsv_to_hsl(h, s, v) {
// both hsv and hsl values are in [0, 1]
var l = (2 - s) * v / 2;
if (l != 0) {
if (l == 1) {
s = 0
} else if (l < 0.5) {
s = s * v / (l * 2)
} else {
s = s * v / (2 - l * 2)
}
}
return [h, s, l]
}
прежде всего, ваш порядок операций приведет к:
b - s / 2 =
50 - 100 / 2 =
50 - 50 = 0
потому что оператор деления имеет более высокий приоритет, чем вычитание. Если вы ожидаете 25, вам нужно сделать (b - s) / 2
вместо.
Я не совсем уверен, что этот результат-то, что вы хотите. Поскольку определения B (V) и L основаны на цветовом пространстве RGB, вам нужен хотя бы способ восстановить значения M и m для расчета преобразование.
посмотреть Википедия статьи для получения дополнительной информации.
Стивен Морли, кажется, получилось здесь.
в частности:
/* Calculates and stores the HSL components of this HSVColour so that they can
* be returned be the getHSL function.
*/
function calculateHSL(){
// determine the lightness in the range [0,100]
var l = (2 - hsv.s / 100) * hsv.v / 2;
// store the HSL components
hsl =
{
'h' : hsv.h,
's' : hsv.s * hsv.v / (l < 50 ? l * 2 : 200 - l * 2),
'l' : l
};
// correct a division-by-zero error
if (isNaN(hsl.s)) hsl.s = 0;
}
он использует [0-360] для hue и [0-100] для других значений.
вы можете попробовать использовать Tinycolor библиотека. Чтобы преобразовать из HSV в HSL, вы можете сделать это
tinycolor("hsv(34, 56%, 100%)").toHslString()
вы должны получить результат что-то вроде этого: "hsl(34, 100%, 72%)"
существует множество формул преобразования между различными цветовыми пространствами:http://www.easyrgb.com/?X=MATH