Observium_CE/html/includes/colours.inc.php

406 lines
8.9 KiB
PHP

<?php
///////// Colour scheme generation - only web useful
// FIXME - snake_case
function rgbToHsl($r, $g, $b)
{
$r /= 255;
$g /= 255;
$b /= 255;
$max = max($r, $g, $b);
$min = min($r, $g, $b);
$l = ($max + $min) / 2;
if ($max == $min) {
// No saturation, this is a shade of gray
$h = $s = 0;
} else {
$delta = $max - $min;
$s = ($l > 0.5) ? $delta / (2 - $max - $min) : $delta / ($max + $min);
switch ($max) {
case $r:
$h = ($g - $b) / $delta + (($g < $b) ? 6 : 0);
break;
case $g:
$h = ($b - $r) / $delta + 2;
break;
case $b:
$h = ($r - $g) / $delta + 4;
break;
}
$h /= 6;
}
return [$h, $s, $l];
}
function hslToRgb($h, $s, $l)
{
if ($s == 0) {
// No saturation, this is a shade of gray
$r = $g = $b = $l * 255;
} else {
$q = ($l < 0.5) ? $l * (1 + $s) : $l + $s - ($l * $s);
$p = (2 * $l) - $q;
$r = round(255 * hueToRgb($p, $q, $h + (1 / 3)));
$g = round(255 * hueToRgb($p, $q, $h));
$b = round(255 * hueToRgb($p, $q, $h - (1 / 3)));
}
return [(int)$r, (int)$g, (int)$b];
}
function hueToRgb($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 darkModeColor($r, $g, $b)
{
// Convert RGB to HSL
[$h, $s, $l] = rgbToHsl($r, $g, $b);
// Invert lightness
$l = 1 - $l;
// Convert back to RGB
return hslToRgb($h, $s, $l);
}
function interpolateRainbow($t)
{
$hue = $t * 360;
return hsvToRgb($hue, 1, 1);
}
function interpolateSinebow($t)
{
$t = 0.5 * ($t + 1);
$t = sin($t * M_PI);
$a = 0.5 * $t * $t;
$b = 0.5 * $t;
$c = 0.5 * $t * sqrt(1 - $t * $t);
return [
255 * (0.5 + $a),
255 * (0.5 + $b),
255 * (0.5 + $c),
];
}
function hsvToRgb($h, $s, $v)
{
$c = $v * $s;
$x = $c * (1 - abs(fmod($h / 60, 2) - 1));
$m = $v - $c;
if ($h < 60) {
$rgb = [$c, $x, 0];
} elseif ($h < 120) {
$rgb = [$x, $c, 0];
} elseif ($h < 180) {
$rgb = [0, $c, $x];
} elseif ($h < 240) {
$rgb = [0, $x, $c];
} elseif ($h < 300) {
$rgb = [$x, 0, $c];
} else {
$rgb = [$c, 0, $x];
}
return [
255 * ($rgb[0] + $m),
255 * ($rgb[1] + $m),
255 * ($rgb[2] + $m),
];
}
/**
* Generates an array of color codes based on the given interpolator function.
*
* @param int $n The number of colors to generate in the palette.
* If 0 or negative, an empty array will be returned.
* If 1, the palette will have a single color generated by the interpolator function.
* @param callable $interpolator A function that takes a float parameter between 0 and 1 (inclusive) and returns an
* array with three elements (red, green, blue) representing the color. Each element
* should be an integer between 0 and 255.
*
* @return array An array of color codes in the format "#RRGGBB", where RR, GG, and BB are two-digit hexadecimal
* values representing the red, green, and blue components of the color.
*/
function generate_palette($n, $interpolator)
{
if ($n <= 0) {
return [];
}
$palette = [];
if ($n == 1) {
$color = call_user_func($interpolator, 0);
$palette[] = sprintf("#%02x%02x%02x", $color[0], $color[1], $color[2]);
return $palette;
}
for ($i = 0; $i < $n; $i++) {
$t = $i / ($n - 1);
$color = call_user_func($interpolator, $t);
$palette[] = sprintf("#%02x%02x%02x", $color[0], $color[1], $color[2]);
}
return $palette;
}
function interpolateSpectral($t)
{
$colors = [
[158, 1, 66],
[213, 62, 79],
[244, 109, 67],
[253, 174, 97],
[254, 224, 139],
[255, 255, 191],
[230, 245, 152],
[171, 221, 164],
[102, 194, 165],
[50, 136, 189],
[94, 79, 162],
];
$segments = count($colors) - 1;
$index = ($t * $segments);
$lower = floor($index);
$upper = ceil($index);
$t = $index - $lower;
if ($lower == $upper) {
return $colors[$lower];
}
return interpolate($t, $colors[$lower], $colors[$upper]);
}
function interpolate($t, $color1, $color2)
{
return [
$color1[0] + $t * ($color2[0] - $color1[0]),
$color1[1] + $t * ($color2[1] - $color1[1]),
$color1[2] + $t * ($color2[2] - $color1[2]),
];
}
function interpolateCubehelix($t, $startAngle = 300, $rotations = -1.5, $hue = 1, $gamma = 1)
{
$angle = 2 * M_PI * (($startAngle / 360) + $rotations * $t);
$fr = $t ** $gamma;
$a = $hue * $fr * (1 - $fr) / 2;
$cosA = cos($angle);
$sinA = sin($angle);
$r = $fr + $a * (-0.14861 * $cosA + 1.78277 * $sinA);
$g = $fr + $a * (-0.29227 * $cosA - 0.90649 * $sinA);
$b = $fr + $a * (1.97294 * $cosA);
return [
(int)round(255 * max(0, min(1, $r))),
(int)round(255 * max(0, min(1, $g))),
(int)round(255 * max(0, min(1, $b))),
];
}
// The interpolateCubehelixDefault function
function interpolateCubehelixDefault($t)
{
return interpolateCubehelix($t, 300, -0.5, 1.7, 0.4);
}
function interpolateCubehelixGreen($t)
{
return interpolateCubehelix($t, 120, -0.5, 1.7, 0.4);
}
function interpolateCubehelixBlueToRed($t)
{
return interpolateCubehelix($t, 240, 0.5, 1.5, 1.0);
}
function interpolateCubehelixRedToGreen($t)
{
return interpolateCubehelix($t, 0, 1.0, 1.5, 1.0);
}
function interpolateCubehelixGrayscale($t)
{
return interpolateCubehelix($t, 0, 0, 0, 1.0);
}
function interpolateCubehelixViridisLike($t)
{
return interpolateCubehelix($t, 260, -0.5, 2.0, 1.0);
}
function interpolateCubehelixSunset($t)
{
return interpolateCubehelix($t, 0, 1.5, 2.0, 1.0);
}
function interpolateCubehelixCoolTones($t)
{
return interpolateCubehelix($t, 200, -0.5, 1.5, 1.0);
}
function interpolateCubehelixEarthTones($t)
{
return interpolateCubehelix($t, 100, -0.5, 1.5, 0.8);
}
function interpolateCubehelixCoolToWarm($t)
{
return interpolateCubehelix($t, 220, 0.5, 1.5, 1.0);
}
function interpolateCubehelixDivergingBlueYellow($t)
{
$middle_t = 0.5;
if ($t < $middle_t) {
return interpolateCubehelix(($middle_t - $t) * 2, 240, -0.5, 1.5, 1.0);
} else {
return interpolateCubehelix(($t - $middle_t) * 2, 60, 0.5, 1.5, 1.0);
}
}
function interpolateCubehelixOcean($t)
{
return interpolateCubehelix($t, 210, -1.0, 1.5, 1.0);
}
function interpolateCubehelixMagmaLike($t)
{
return interpolateCubehelix($t, 0, 1.5, 1.8, 1.0);
}
function interpolateCubehelixPastel($t)
{
return interpolateCubehelix($t, 300, 0.8, 0.7, 1.2);
}
function divergingColorMap($t, $colors)
{
$n = count($colors) - 1;
$index = min($n - 1, max(0, floor($t * $n)));
$t = ($t * $n) - $index;
return interpolateColor($t, $colors[$index], $colors[$index + 1]);
}
function interpolateRdYlBu($t)
{
$colors = [
[165, 0, 38],
[215, 48, 39],
[244, 109, 67],
[253, 174, 97],
[254, 224, 144],
[255, 255, 191],
[224, 243, 248],
[171, 217, 233],
[116, 173, 209],
[69, 117, 180],
[49, 54, 149],
];
return divergingColorMap($t, $colors);
}
function interpolateRdBu($t)
{
$colors = [
[103, 0, 31],
[178, 24, 43],
[214, 96, 77],
[244, 165, 130],
[253, 219, 199],
[247, 247, 247],
[209, 229, 240],
[146, 197, 222],
[67, 147, 195],
[33, 102, 172],
[5, 48, 97],
];
return divergingColorMap($t, $colors);
}
function interpolatePuOr($t)
{
$colors = [
[127, 59, 8],
[179, 88, 6],
[224, 130, 20],
[253, 184, 99],
[254, 224, 182],
[247, 247, 247],
[216, 218, 235],
[178, 171, 210],
[128, 115, 172],
[84, 39, 136],
[45, 0, 75],
];
return divergingColorMap($t, $colors);
}
function interpolateBrBG($t)
{
$colors = [
[84, 48, 5],
[140, 81, 10],
[191, 129, 45],
[223, 194, 125],
[246, 232, 195],
[245, 245, 245],
[199, 234, 229],
[128, 205, 193],
[53, 151, 143],
[1, 102, 94],
[0, 60, 48],
];
return divergingColorMap($t, $colors);
}
function interpolateCividis($t)
{
$colors = [
[0, 32, 76],
[0, 42, 102],
[0, 52, 110],
[12, 69, 132],
[38, 87, 141],
[61, 104, 147],
[83, 121, 153],
[109, 138, 158],
[134, 154, 163],
[160, 170, 168],
[185, 186, 172],
];
return divergingColorMap($t, $colors);
}