index/src/Colour/ColourHSL.php

128 lines
3.1 KiB
PHP

<?php
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()
);
}
}