[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/vendor/splitbrain/lesserphp/src/Utils/ -> Color.php (source)

   1  <?php
   2  
   3  namespace LesserPHP\Utils;
   4  
   5  use LesserPHP\Constants;
   6  
   7  /**
   8   * Color handling utilities
   9   */
  10  class Color
  11  {
  12      /**
  13       * coerce a value for use in color operation
  14       * returns null if the value can't be used in color operations
  15       */
  16      public static function coerceColor(array $value): ?array
  17      {
  18          switch ($value[0]) {
  19              case 'color':
  20                  return $value;
  21              case 'raw_color':
  22                  $c = ['color', 0, 0, 0];
  23                  $colorStr = substr($value[1], 1);
  24                  $num = hexdec($colorStr);
  25                  $width = strlen($colorStr) == 3 ? 16 : 256;
  26  
  27                  for ($i = 3; $i > 0; $i--) { // 3 2 1
  28                      $t = $num % $width;
  29                      $num /= $width;
  30  
  31                      $c[$i] = $t * (256 / $width) + $t * floor(16 / $width);
  32                  }
  33  
  34                  return $c;
  35              case 'keyword':
  36                  $name = $value[1];
  37                  if (isset(Constants::CSS_COLORS[$name])) {
  38                      $rgba = explode(',', Constants::CSS_COLORS[$name]);
  39  
  40                      if (isset($rgba[3]))
  41                          return ['color', $rgba[0], $rgba[1], $rgba[2], $rgba[3]];
  42  
  43                      return ['color', $rgba[0], $rgba[1], $rgba[2]];
  44                  }
  45                  return null;
  46          }
  47          return null;
  48      }
  49  
  50      /**
  51       * Calculate the perceptual brightness of a color object
  52       */
  53      public static function toLuma(array $color): float
  54      {
  55          [, $r, $g, $b] = Color::coerceColor($color);
  56  
  57          $r = $r / 255;
  58          $g = $g / 255;
  59          $b = $b / 255;
  60  
  61          $r = ($r <= 0.03928) ? $r / 12.92 : (($r + 0.055) / 1.055) ** 2.4;
  62          $g = ($g <= 0.03928) ? $g / 12.92 : (($g + 0.055) / 1.055) ** 2.4;
  63          $b = ($b <= 0.03928) ? $b / 12.92 : (($b + 0.055) / 1.055) ** 2.4;
  64  
  65          return (0.2126 * $r) + (0.7152 * $g) + (0.0722 * $b);
  66      }
  67  
  68      /**
  69       * Convert a color to HSL color space
  70       */
  71      public static function toHSL(array $color): array
  72      {
  73          if ($color[0] == 'hsl') return $color;
  74  
  75          $r = $color[1] / 255;
  76          $g = $color[2] / 255;
  77          $b = $color[3] / 255;
  78  
  79          $min = min($r, $g, $b);
  80          $max = max($r, $g, $b);
  81  
  82          $L = ($min + $max) / 2;
  83          if ($min == $max) {
  84              $S = $H = 0;
  85          } else {
  86              if ($L < 0.5) {
  87                  $S = ($max - $min) / ($max + $min);
  88              } else {
  89                  $S = ($max - $min) / (2.0 - $max - $min);
  90              }
  91  
  92              if ($r == $max) {
  93                  $H = ($g - $b) / ($max - $min);
  94              } elseif ($g == $max) {
  95                  $H = 2.0 + ($b - $r) / ($max - $min);
  96              } elseif ($b == $max) {
  97                  $H = 4.0 + ($r - $g) / ($max - $min);
  98              } else {
  99                  $H = 0;
 100              }
 101          }
 102  
 103          $out = [
 104              'hsl',
 105              ($H < 0 ? $H + 6 : $H) * 60,
 106              $S * 100,
 107              $L * 100,
 108          ];
 109  
 110          if (count($color) > 4) $out[] = $color[4]; // copy alpha
 111          return $out;
 112      }
 113  
 114  
 115      /**
 116       * Converts a hsl array into a color value in rgb.
 117       * Expects H to be in range of 0 to 360, S and L in 0 to 100
 118       */
 119      public static function toRGB(array $color): array
 120      {
 121          if ($color[0] == 'color') return $color;
 122  
 123          $H = $color[1] / 360;
 124          $S = $color[2] / 100;
 125          $L = $color[3] / 100;
 126  
 127          if ($S == 0) {
 128              $r = $g = $b = $L;
 129          } else {
 130              $temp2 = $L < 0.5 ?
 131                  $L * (1.0 + $S) :
 132                  $L + $S - $L * $S;
 133  
 134              $temp1 = 2.0 * $L - $temp2;
 135  
 136              $r = self::calculateRGBComponent($H + 1 / 3, $temp1, $temp2);
 137              $g = self::calculateRGBComponent($H, $temp1, $temp2);
 138              $b = self::calculateRGBComponent($H - 1 / 3, $temp1, $temp2);
 139          }
 140  
 141          // $out = array('color', round($r*255), round($g*255), round($b*255));
 142          $out = ['color', $r * 255, $g * 255, $b * 255];
 143          if (count($color) > 4) $out[] = $color[4]; // copy alpha
 144          return $out;
 145      }
 146  
 147  
 148      /**
 149       * make sure a color's components don't go out of bounds
 150       */
 151      public static function fixColor(array $c): array
 152      {
 153          foreach (range(1, 3) as $i) {
 154              if ($c[$i] < 0) $c[$i] = 0;
 155              if ($c[$i] > 255) $c[$i] = 255;
 156          }
 157  
 158          return $c;
 159      }
 160  
 161      /**
 162       * Helper function for the HSL to RGB conversion process.
 163       *
 164       * This function normalizes the input component of the HSL color and determines the RGB
 165       * value based on the HSL values.
 166       *
 167       * @param float $comp The component of the HSL color to be normalized and converted.
 168       * @param float $temp1 The first temporary variable used in the conversion process
 169       * @param float $temp2 The second temporary variable used in the conversion process
 170       *
 171       * @return float The calculated RGB value as percentage of the maximum value (255)
 172       */
 173      protected static function calculateRGBComponent(float $comp, float $temp1, float $temp2): float
 174      {
 175          // Normalize the component value to be within the range [0, 1]
 176          if ($comp < 0) $comp += 1.0;
 177          elseif ($comp > 1) $comp -= 1.0;
 178  
 179          // Determine the return value based on the value of the component
 180          if (6 * $comp < 1) return $temp1 + ($temp2 - $temp1) * 6 * $comp;
 181          if (2 * $comp < 1) return $temp2;
 182          if (3 * $comp < 2) return $temp1 + ($temp2 - $temp1) * ((2 / 3) - $comp) * 6;
 183  
 184          // Fallback return value, represents the case where the saturation of the color is zero
 185          return $temp1;
 186      }
 187  }