【问题标题】:PHP function to convert HSL to RGB or Hex将 HSL 转换为 RGB 或 Hex 的 PHP 函数
【发布时间】:2013-12-23 18:56:17
【问题描述】:

有谁知道可以将 HSL 颜色转换为 RGB 或 Hex 的 PHP 函数(用于 >5.3)?我已经尝试了十几个 Google 搜索,但我发现的所有功能都没有按预期工作。

函数转换为 RGB 还是十六进制并不重要,因为这两者之间的转换是微不足道的。输入是 CSS 的 HSL 值(色调:0–360,饱和度:0–100,亮度:0–100)。

编辑:指定输入和输出格式将是一个奖励:)

【问题讨论】:

  • 那么,你找到的东西出了什么问题?你确定你没有试图以意想不到的方式使用它们吗?
  • 您可能需要编写自己的函数,但这里有一个来自相关答案的模板:stackoverflow.com/questions/11804027/…
  • 输出要么是看似随机的数字,要么是在某些情况下是三个相同的数字。我试图更改提供参数的方式(命名数组等以解决三个相同的数字情况),但我无法获得预期的输出。我发现的函数的部分问题是预期的参数和输出格式没有记录,虽然输出格式可以从代码中推断出来,但参数格式很难从这样的数学函数中计算出来。跨度>
  • @Jim 所以函数 (HSVtoRGB) 需要一个色调 (0–360)、饱和度 (0–1) 和亮度 (0–1) 的数组,并返回一个红色、绿色和蓝色的数组?

标签: php css hsl


【解决方案1】:

从 Jim 的评论链接 (PHP HSV to RGB formula comprehension) 中的一个答案中获取代码,我们可以计算如下:

<?php    
    $hue = 209;
    $sat = 75;
    $lum = 60;

    $hue /= 360;
    $sat /= 100;
    $lum /= 100;

    $result = ColorHSLToRGB($hue, $sat, $lum);
    var_dump($result); echo '<br>';
    printf("rgb = %d,%d,%d<br>", $result['r'], $result['g'], $result['b']);




function ColorHSLToRGB($h, $s, $l){

        $r = $l;
        $g = $l;
        $b = $l;
        $v = ($l <= 0.5) ? ($l * (1.0 + $s)) : ($l + $s - $l * $s);
        if ($v > 0){
              $m;
              $sv;
              $sextant;
              $fract;
              $vsf;
              $mid1;
              $mid2;

              $m = $l + $l - $v;
              $sv = ($v - $m ) / $v;
              $h *= 6.0;
              $sextant = floor($h);
              $fract = $h - $sextant;
              $vsf = $v * $sv * $fract;
              $mid1 = $m + $vsf;
              $mid2 = $v - $vsf;

              switch ($sextant)
              {
                    case 0:
                          $r = $v;
                          $g = $mid1;
                          $b = $m;
                          break;
                    case 1:
                          $r = $mid2;
                          $g = $v;
                          $b = $m;
                          break;
                    case 2:
                          $r = $m;
                          $g = $v;
                          $b = $mid1;
                          break;
                    case 3:
                          $r = $m;
                          $g = $mid2;
                          $b = $v;
                          break;
                    case 4:
                          $r = $mid1;
                          $g = $m;
                          $b = $v;
                          break;
                    case 5:
                          $r = $v;
                          $g = $m;
                          $b = $mid2;
                          break;
              }
        }
        return array('r' => $r * 255.0, 'g' => $g * 255.0, 'b' => $b * 255.0);
}
?>

输出:

array(3) { ["r"]=> float(76.5) ["g"]=> float(155.55) ["b"]=> float(229.5) } 
rgb = 76,155,229

【讨论】:

  • 感谢您将这些放在一起。我在我的一个网站上使用过,它似乎有效,因为我使用的是随机颜色。但是,我注意到如果我只是通过 0 到 359 的色调值,我也会得到完全随机的数字。这个函数真的正确吗?
  • 没问题,不客气。是的,虽然 hsl 和 rgb 之间的关系是完全不直观的,并且 H 的平滑变化同时保持 S 和 L 值会导致 rgb 值发生剧烈变化。玩一下图像编辑程序,然后将吸管拖到 hsl 颜色选择样本的图片上 - rgb 值将以相同的方式变化。 ;) - 我多年来一直使用此代码来生成它们。
  • 这真的很奇怪。我确实看到,大多数从 HSL 到 RGB 的谷歌结果看起来很奇怪,几乎是深奥的。但是当我在 Chrome 检查器中,单击 CSS 颜色设置并切换到 HSL 时,我只需单击 0 到 359 就可以得到我所期望的:我连续遍历整个色轮。现在出了什么问题?
  • @SwissMister - 抱歉耽搁了。恐怕我不明白你在这里的意思。 (0) 我在 Chrome 的工具中看不到色轮。 (1) 我看不到可以点击 0-360(或 359)的地方 (2) 我知道(我认为)你在期待什么,但不知道你在期待什么'正在得到 - 明确说明每一个都很少是一个问题。通常或至少经常不这样做是。
  • 0:imgur.com/a/s0MFC -> 1:滚动“H”字段的值 -> 2:我仍然很好奇为什么没有 HSL2RGB 函数可以做到这一点。你有什么想法吗?
【解决方案2】:

把这些放在一起(这帮助我产生了this chart

/**
 * convert a HSL colorscheme to either Hexadecimal (default) or RGB.
 * 
 * We want a method where we can programmatically generate a series of colors
 * between two values (eg. red to green) which is easy to do with HSL because
 * you just change the hue. (0 = red, 120 = green).  You can use this function
 * to convert those hsl color values to either the rgb or hexadecimal color scheme.
 * e.g. You have
 *   hsl(50, 100%, 50%)
 * To convert,
 * $hex = convertHSL(50,100,50);  // returns #ffd500
 * or 
 * $rgb = convertHSL(50,100,50, false);  // returns rgb(255, 213, 0)
 *  
 * see https://coderwall.com/p/dvsxwg/smoothly-transition-from-green-to-red
 * @param int $h the hue
 * @param int $s the saturation
 * @param int $l the luminance
 * @param bool $toHex whether you want hexadecimal equivalent or rgb equivalent
 * @return string usable in HTML or CSS
 */

function convertHSL($h, $s, $l, $toHex=true){
    $h /= 360;
    $s /=100;
    $l /=100;

    $r = $l;
    $g = $l;
    $b = $l;
    $v = ($l <= 0.5) ? ($l * (1.0 + $s)) : ($l + $s - $l * $s);
    if ($v > 0){
          $m;
          $sv;
          $sextant;
          $fract;
          $vsf;
          $mid1;
          $mid2;

          $m = $l + $l - $v;
          $sv = ($v - $m ) / $v;
          $h *= 6.0;
          $sextant = floor($h);
          $fract = $h - $sextant;
          $vsf = $v * $sv * $fract;
          $mid1 = $m + $vsf;
          $mid2 = $v - $vsf;

          switch ($sextant)
          {
                case 0:
                      $r = $v;
                      $g = $mid1;
                      $b = $m;
                      break;
                case 1:
                      $r = $mid2;
                      $g = $v;
                      $b = $m;
                      break;
                case 2:
                      $r = $m;
                      $g = $v;
                      $b = $mid1;
                      break;
                case 3:
                      $r = $m;
                      $g = $mid2;
                      $b = $v;
                      break;
                case 4:
                      $r = $mid1;
                      $g = $m;
                      $b = $v;
                      break;
                case 5:
                      $r = $v;
                      $g = $m;
                      $b = $mid2;
                      break;
          }
    }
    $r = round($r * 255, 0);
    $g = round($g * 255, 0);
    $b = round($b * 255, 0);

    if ($toHex) {
        $r = ($r < 15)? '0' . dechex($r) : dechex($r);
        $g = ($g < 15)? '0' . dechex($g) : dechex($g);
        $b = ($b < 15)? '0' . dechex($b) : dechex($b);
        return "#$r$g$b";
    } else {
        return "rgb($r, $g, $b)";    
    }

【讨论】:

    【解决方案3】:

    我对所有其他实现的测试只显示了奇怪且可能不可信的结果。这是来自https://stackoverflow.com/a/9493060/1598477 的@Mohsen 代码的PHP 实现。再加上一个测试来展示完整的美丽......

    很抱歉交叉发布此内容。但我真的没有看到任何其他实现可以提供我需要的质量。

    /**
     * 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 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;
            }
    function hslToRgb($h, $s, $l){
        if($s == 0){
            $r = $l;
            $g = $l;
            $b = $l; // achromatic
        }else{
            $q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s;
            $p = 2 * $l - $q;
            $r = hue2rgb($p, $q, $h + 1/3);
            $g = hue2rgb($p, $q, $h);
            $b = hue2rgb($p, $q, $h - 1/3);
        }
    
        return array(round($r * 255), round($g * 255), round($b * 255));
    }
    
    /* Uncomment to test * /
    for ($i=0;$i<360;$i++) {
      $rgb=hslToRgb($i/360, 1, .9);
      echo '<div style="background-color:rgb(' .$rgb[0] . ', ' . $rgb[1] . ', ' . $rgb[2] . ');padding:2px;"></div>';
    }
    /* End Test */
    

    【讨论】:

      【解决方案4】:

      PEAR 包 Image_Color2 具有在颜色模型之间转换的方法 - 请参阅 convertTo

      【讨论】:

        【解决方案5】:

        这是我的解决方案

        HSV 值限制:$H [0-359]、$S [0-100]、$V [0-100]

        function hsv_to_rgb($iH, $iS, $iV) {
        
            if($iH < 0)   $iH = 0;
            if($iH > 360) $iH = 360;
            if($iS < 0)   $iS = 0;
            if($iS > 100) $iS = 100;
            if($iV < 0)   $iV = 0;
            if($iV > 100) $iV = 100;
            $dS = $iS/100.0;
            $dV = $iV/100.0;
            $dC = $dV*$dS;
            $dH = $iH/60.0;
            $dT = $dH;
            while($dT >= 2.0) $dT -= 2.0; // php modulus does not work with float
            $dX = $dC*(1-abs($dT-1));     // as used in the Wikipedia link
            switch($dH) {
              case($dH >= 0.0 && $dH < 1.0):
                $dR = $dC; $dG = $dX; $dB = 0.0; break;
              case($dH >= 1.0 && $dH < 2.0):
                $dR = $dX; $dG = $dC; $dB = 0.0; break;
              case($dH >= 2.0 && $dH < 3.0):
                $dR = 0.0; $dG = $dC; $dB = $dX; break;
              case($dH >= 3.0 && $dH < 4.0):
                $dR = 0.0; $dG = $dX; $dB = $dC; break;
              case($dH >= 4.0 && $dH < 5.0):
                $dR = $dX; $dG = 0.0; $dB = $dC; break;
              case($dH >= 5.0 && $dH < 6.0):
                $dR = $dC; $dG = 0.0; $dB = $dX; break;
              default:
                $dR = 0.0; $dG = 0.0; $dB = 0.0; break;
            }
            $dM  = $dV - $dC;
            $dR += $dM; $dG += $dM; $dB += $dM;
            $dR *= 255; $dG *= 255; $dB *= 255;
            return array(round($dR), round($dG), round($dB));
          }
        

        【讨论】:

          【解决方案6】:

          复制自this SO AnswerCullub

          此代码完美地将用户电子邮件转换为用户头像颜色。经过长时间的搜索,我得到了正确的十六进制值,类似于在前端使用 javascript 生成的十六进制值。

          TL;DR:完整的代码可以在这里找到Pastebin

          /**
           * convert user email to hsl for user avatar
           * @param string $string
           * @return string HEX color code
           */
          function stringToColor($string)
          {
              $hash = 0;
              $l = 70;
              $s = 60;
              for ($i = 0; $i < strlen($string); $i++) {
                  $hash = ord($string[$i]) + (($hash << 5) - $hash);
              }
              $h = fmod($hash, 360);
              return $this->hslToHex($h, $s, $l, true);
          }
          
          /**
           * 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 = $this->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 format
                      return false;
                  }
              }
              if (strlen($hexG) != 2) {
                  if (strlen($hexG) == 1) {
                      $hexG = "0" . $hexG;
                  } else {
                      return false;
                  }
              }
              if (strlen($hexB) != 2) {
                  if (strlen($hexB) == 1) {
                      $hexB = "0" . $hexB;
                  } else {
                      return false;
                  }
              }
          
              //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;
          }
          /**
           * 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)
          {
              //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;
          
              //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 * $this->hueToRgb($temp1, $temp2, $h + (1 / 3));
                  $g = 255 * $this->hueToRgb($temp1, $temp2, $h);
                  $b = 255 * $this->hueToRgb($temp1, $temp2, $h - (1 / 3));
              }
              $rgb['r'] = $r;
              $rgb['g'] = $g;
              $rgb['b'] = $b;
              return $rgb;
              // return "rgb($r, $g, $b)";
          }
          /**
           * 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;
          }
          

          【讨论】:

            【解决方案7】:

            如果您有十进制 RGB 值(enhzflep 展示了如何获取它们),您可以轻松获取 #ab01cd 十六进制网络字符串:

            $rgb['r'] = ($t = round($rgb['r'] * 255, 0)) < 15 ? '0'.dechex($t) : dechex($t);
            $rgb['g'] = ($t = round($rgb['g'] * 255, 0)) < 15 ? '0'.dechex($t) : dechex($t);
            $rgb['b'] = ($t = round($rgb['b'] * 255, 0)) < 15 ? '0'.dechex($t) : dechex($t);
            $hexweb = "#".$rgb['r'].$rgb['g'].$rgb['b'];
            

            【讨论】:

            • 这在他获得 RGB 后可能很有用,但它不能回答问题。顺便说一句,这可以简化为'#'.str_pad(dechex(($r&lt;&lt;16) + ($g&lt;&lt;8) + $b),6,'0',STR_PAD_LEFT);
            猜你喜欢
            • 1970-01-01
            • 2016-08-11
            • 2022-11-25
            • 1970-01-01
            • 1970-01-01
            • 2017-07-26
            • 2013-11-12
            • 1970-01-01
            • 2021-06-29
            相关资源
            最近更新 更多