2023-01-02 03:23:48 +00:00
|
|
|
<?php
|
2023-01-02 03:24:41 +00:00
|
|
|
// ColourHSL.php
|
|
|
|
// Created: 2023-01-02
|
|
|
|
// Updated: 2023-01-02
|
|
|
|
|
2023-01-02 03:23:48 +00:00
|
|
|
namespace Index\Colour;
|
|
|
|
|
|
|
|
class ColourHSL extends Colour {
|
|
|
|
private float $hue;
|
|
|
|
private float $saturation;
|
|
|
|
private float $lightness;
|
|
|
|
private float $alpha;
|
|
|
|
|
|
|
|
private int $red;
|
|
|
|
private int $green;
|
|
|
|
private int $blue;
|
|
|
|
|
|
|
|
public function __construct(float $hue, float $saturation, float $lightness, float $alpha) {
|
|
|
|
$hue %= 360;
|
|
|
|
|
|
|
|
$this->hue = $hue;
|
|
|
|
$this->saturation = max(0.0, min(1.0, $saturation));
|
|
|
|
$this->lightness = max(0.0, min(1.0, $lightness));
|
|
|
|
$this->alpha = max(0.0, min(1.0, $alpha));
|
|
|
|
|
|
|
|
$c = (1 - abs(2 * $lightness - 1)) * $saturation;
|
|
|
|
$x = $c * (1 - abs(fmod($hue / 60, 2) - 1));
|
|
|
|
$m = $lightness - ($c / 2);
|
|
|
|
|
|
|
|
$r = $g = $b = 0;
|
|
|
|
|
|
|
|
if($hue < 60) {
|
|
|
|
$r = $c;
|
|
|
|
$g = $x;
|
|
|
|
} elseif($hue < 120) {
|
|
|
|
$r = $x;
|
|
|
|
$g = $c;
|
|
|
|
} elseif($hue < 180) {
|
|
|
|
$g = $c;
|
|
|
|
$b = $x;
|
|
|
|
} elseif($hue < 240) {
|
|
|
|
$g = $x;
|
|
|
|
$b = $c;
|
|
|
|
} elseif($hue < 300) {
|
|
|
|
$r = $x;
|
|
|
|
$b = $c;
|
|
|
|
} else {
|
|
|
|
$r = $c;
|
|
|
|
$b = $x;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->red = (int)round(($r + $m) * 255);
|
|
|
|
$this->green = (int)round(($g + $m) * 255);
|
|
|
|
$this->blue = (int)round(($b + $m) * 255);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getRed(): int {
|
|
|
|
return $this->red;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getGreen(): int {
|
|
|
|
return $this->green;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getBlue(): int {
|
|
|
|
return $this->blue;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getHue(): float {
|
|
|
|
return $this->hue;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getSaturation(): float {
|
|
|
|
return $this->saturation;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getLightness(): float {
|
|
|
|
return $this->lightness;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAlpha(): float {
|
|
|
|
return $this->alpha;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function shouldInherit(): bool {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __toString(): string {
|
|
|
|
if($this->alpha < 1.0)
|
|
|
|
return sprintf('hsla(%.2Fdeg, %d%%, %d%%, %.3F)', $this->hue, $this->saturation * 100, $this->lightness * 100, $this->alpha);
|
|
|
|
return sprintf('hsl(%.2Fdeg, %d%%, %d%%)', $this->hue, $this->saturation * 100, $this->lightness * 100);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function convert(Colour $colour): ColourHSL {
|
|
|
|
if($colour instanceof ColourHSL)
|
|
|
|
return $colour;
|
|
|
|
|
|
|
|
$r = $colour->getRed() / 255.0;
|
|
|
|
$g = $colour->getGreen() / 255.0;
|
|
|
|
$b = $colour->getBlue() / 255.0;
|
|
|
|
|
|
|
|
$max = max($r, $g, $b);
|
|
|
|
$min = min($r, $g, $b);
|
|
|
|
|
|
|
|
$h = $s = 0;
|
|
|
|
$l = ($max + $min) / 2;
|
|
|
|
$d = $max - $min;
|
|
|
|
|
|
|
|
if($d <> 0) {
|
|
|
|
$s = $d / (1 - abs(2 * $l - 1));
|
|
|
|
|
|
|
|
if($max == $r) {
|
|
|
|
$h = 60 * fmod((($g - $b) / $d), 6);
|
|
|
|
if($b > $g)
|
|
|
|
$h += 360;
|
|
|
|
} elseif($max == $g) {
|
|
|
|
$h = 60 * (($b - $r) / $d + 2);
|
|
|
|
} else {
|
|
|
|
$h = 60 * (($r - $g) / $d + 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return new ColourHSL(
|
|
|
|
round($h, 3),
|
|
|
|
round($s, 3),
|
|
|
|
round($l, 3),
|
|
|
|
$colour->getAlpha()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|