سؤال

هل أقوم بتحويل لون 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؟

هل كانت مفيدة؟

المحلول

أخشى أن تعرف معرفتي JavaScript ، لكن يجب أن تكون قادرًا على استنتاج التحويل من http://ariya.blogspot.com/2008/07/converting-between-hsl-and-hsv.html

نصائح أخرى

دعونا نصور ما هو في الواقع حSB(5) ، حSL, ، وكيف يتم بناؤها:

Convert HSB to HSL - Color picker

مسحة تنتقل قيمة اللون من 0 ل 360 الدرجات (حيث 0 أحمر) لكل من HSB و HSL.
علاوة على ذلك يتم تطبيق هذا طبقات التدرج الخطية

HSB (المعروف أيضًا باسم HSV)

  • مسحة
  • التشبع = (من اليسار) أبيضشفاف
  • سطوع (قيمة) = (من أسفل) أسودشفاف

HSL

  • مسحة
  • التشبع = (من اليسار) رمادي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 ;
}

للتحويل إلى غير عائم %قيم النسبة المئوية نحب:

(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 ، فأنت بحاجة إلى طريقة على الأقل لاستعادة قيم م و م لحساب التحويل.

انظر ويكيبيديا مقال لمزيد من المعلومات.

يبدو أن ستيفن مورلي قد سمّرها هنا.

على وجه التحديد:

/* 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] للقيم الأخرى.

جرب هذا (S ، V ، L في [0،1] ، ويكي تفاصيل, ، أكثر: HSV2RGB RGB2HSV و HSL2RGB RGB2HSL)

let hsv2hsl = (h,s,v,l=v-v*s/2,m=Math.min(l,1-l)) => [h,m?(v-l)/m:0,l];

let hsl2hsv = (h,s,l,v=s*Math.min(l,1-l)+l) => [h, v?2-2*l/v:0, v];

let hsv2hsl = (h,s,v,l=v-v*s/2,m=Math.min(l,1-l)) => [h,m?(v-l)/m:0,l];
let hsl2hsv = (h,s,l,v=s*Math.min(l,1-l)+l) => [h, v?2-2*l/v:0, v];

console.log("hsv:["+ hsl2hsv(30,1,0.6) +"] hsl:["+ hsv2hsl(30,0.8,1) +"]");


// -------------------
// UI code
// -------------------

let $ = x => document.querySelector(x);
let c = (x,s) => $(x).style.backgroundColor=s;
let hsl=[0,1,0.5];
let hsv=hsl2hsv(...hsl);

let refreshHSV =(i,e) => {
   hsv[i]= e.target.value/(i?100:1);
   hsl=hsv2hsl(...hsv);
   refreshView();
}

let refreshHSL =(i,e) => {
   hsl[i]= e.target.value/(i?100:1);
   hsv=hsl2hsv(...hsl);  
   refreshView();
}

let hsv2rgb = (h,s,v) => {                              
  let f= (n,k=(n+h/60)%6) => v - v*s*Math.max( Math.min(k,4-k,1), 0);     
  return [f(5),f(3),f(1)];       
}

let refreshView = () => {
   let a= [hsl[0], (hsl[1]*100).toFixed(2), (hsl[2]*100).toFixed(2)]; 
   let b= [hsv[0], (hsv[1]*100).toFixed(2), (hsv[2]*100).toFixed(2)]; 
   
   let r= hsv2rgb(...hsv).map(x=>x*255|0);
   let ta= `hsl(${a[0]},${a[1]}%,${a[2]}%)`
   let tb= `hsv(${b[0]},${b[1]}%,${b[2]}%)`
   let tr= `rgb(${r[0]},${r[1]},${r[2]})`
   
   c('.hsl', tr);   
   $('#sv').value=hsv[1]*100;
   $('#v').value =hsv[2]*100;
   $('#sl').value=hsl[1]*100;
   $('#l').value =hsl[2]*100;
   $('.info').innerHTML=`${tr}\n${tb}\n${ta.padEnd(25)}`;   
}



refreshView();
.box {
  width: 50px;
  height: 50px;
  margin: 20px;
}

body {
    display: flex;
}
<div>
<input id="h" type="range" min="0" max="360" value="0" oninput="refreshHSV(0,event)">Hue<br>
<div class="box hsl"></div>
<pre class="info"></pre>
</div> 

<div>
<input id="sv" type="range" min="0" max="100" value="0" oninput="refreshHSV(1,event)">HSV Saturation<br>
<input id="v" type="range" min="0" max="100" value="100" oninput="refreshHSV(2,event)">HSV Value<br><br><br>
<input id="sl" type="range" min="0" max="100" value="0" oninput="refreshHSL(1,event)">HSL Saturation<br>
<input id="l" type="range" min="0" max="100" value="100" oninput="refreshHSL(2,event)">HSL Lightness<br>
</div>

يمكنك محاولة استخدام الألوان الصغيرة مكتبة. للتحويل من HSV إلى HSL ، يمكنك القيام بذلك

tinycolor("hsv(34, 56%, 100%)").toHslString()

يجب أن تحصل على نتيجة مثل هذا: "HSL (34 ، 100 ٪ ، 72 ٪)"

هناك الكثير من صيغ التحويل بين مساحات الألوان المختلفة: http://www.easyrgb.com/؟x=math

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top