xref: /webtrees/app/Statistics/Service/ColorService.php (revision 9d74ed0ab3ae61aa8ae07578e026f14020844ce9)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2023 webtrees development team
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\Statistics\Service;
21
22use function array_map;
23use function hexdec;
24use function ltrim;
25use function round;
26use function sprintf;
27
28/**
29 * Functions for managing and manipulating colors.
30 */
31class ColorService
32{
33    /**
34     * Interpolates the number of color steps between a given start and end color.
35     *
36     * @param string $startColor The start color
37     * @param string $endColor   The end color
38     * @param int    $steps      The number of steps to interpolate
39     *
40     * @return array<string>
41     */
42    public function interpolateRgb(string $startColor, string $endColor, int $steps): array
43    {
44        if ($steps === 0) {
45            return [];
46        }
47
48        $s       = $this->hexToRgb($startColor);
49        $e       = $this->hexToRgb($endColor);
50        $colors  = [];
51        $factorR = ($e[0] - $s[0]) / $steps;
52        $factorG = ($e[1] - $s[1]) / $steps;
53        $factorB = ($e[2] - $s[2]) / $steps;
54
55        for ($x = 1; $x < $steps; ++$x) {
56            $colors[] = $this->rgbToHex(
57                (int) round($s[0] + $factorR * $x),
58                (int) round($s[1] + $factorG * $x),
59                (int) round($s[2] + $factorB * $x)
60            );
61        }
62
63        $colors[] = $this->rgbToHex($e[0], $e[1], $e[2]);
64
65        return $colors;
66    }
67
68    /**
69     * Converts the color values to the HTML hex representation.
70     *
71     * @param int $r The red color value
72     * @param int $g The green color value
73     * @param int $b The blue color value
74     *
75     * @return string
76     */
77    private function rgbToHex(int $r, int $g, int $b): string
78    {
79        return sprintf('#%02x%02x%02x', $r, $g, $b);
80    }
81
82    /**
83     * Converts the HTML color hex representation to an array of color values.
84     *
85     * @param string $hex The HTML hex color code
86     *
87     * @return array<int>
88     */
89    private function hexToRgb(string $hex): array
90    {
91        return array_map(static fn (string $hex): int => (int) hexdec($hex), str_split(ltrim($hex, '#'), 2));
92    }
93}
94