Completed
Pull Request — master (#1)
by ARCANEDEV
03:03
created

HSVTrait::calculateRgbWithHueAndChroma()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 8.2222
c 0
b 0
f 0
cc 7
eloc 11
nc 7
nop 2
1
<?php namespace Arcanedev\Color\Converters;
2
3
/**
4
 * Trait     HSVTrait
5
 *
6
 * @package  Arcanedev\Color\Converters
7
 * @author   ARCANEDEV <[email protected]>
8
 */
9
trait HSVTrait
10
{
11
    /* ------------------------------------------------------------------------------------------------
12
     |  Main Functions
13
     | ------------------------------------------------------------------------------------------------
14
     */
15
    /**
16
     * Convert an RGB color to an HSV array (alias).
17
     *
18
     * @see    fromRgbToHsv
19
     *
20
     * @param  int  $red
21
     * @param  int  $green
22
     * @param  int  $blue
23
     *
24
     * @return array
25
     */
26
    public static function rgbToHsv($red, $green, $blue)
27
    {
28
        return (new self())->fromRgbToHsv($red, $green, $blue);
29
    }
30
31
    /**
32
     * Convert an RGB color to an HSV array.
33
     *
34
     * @param  int  $red
35
     * @param  int  $green
36
     * @param  int  $blue
37
     *
38
     * @return array
39
     */
40
    public function fromRgbToHsv($red, $green, $blue)
41
    {
42
        $red        = $red   / 255;
43
        $green      = $green / 255;
44
        $blue       = $blue  / 255;
45
        $maxRGB     = max($red, $green, $blue);
46
        $minRGB     = min($red, $green, $blue);
47
48
        $hue        = 0;
49
        $saturation = 0;
50
        $value      = 100 * $maxRGB;
51
        $chroma     = $maxRGB - $minRGB;
52
53
        if ($chroma != 0) {
54
            $saturation = 100 * ($chroma / $maxRGB);
55
56
            if ($red == $minRGB)
57
                $hue = 3 - (($green - $blue) / $chroma);
58
            elseif ($blue == $minRGB)
59
                $hue = 1 - (($red - $green) / $chroma);
60
            else // $green == $minRGB
61
                $hue = 5 - (($blue - $red) / $chroma);
62
63
            $hue = 60 * $hue;
64
        }
65
66
        return [
67
            round($hue, 2),
68
            round($saturation, 2),
69
            round($value, 2),
70
        ];
71
    }
72
73
    /**
74
     * Convert an HSV color to an RGB array (alias).
75
     *
76
     * @see    fromHsvToRgb
77
     *
78
     * @param  float|int  $hue
79
     * @param  float|int  $saturation
80
     * @param  float|int  $value
81
     *
82
     * @return array
83
     */
84
    public static function hsvToRgb($hue, $saturation, $value)
85
    {
86
        return (new self)->fromHsvToRgb($hue, $saturation, $value);
87
    }
88
89
    /**
90
     * Convert an HSV color to an RGB array.
91
     *
92
     * @param  float|int  $hue
93
     * @param  float|int  $saturation
94
     * @param  float|int  $value
95
     *
96
     * @return array
97
     */
98
    public function fromHsvToRgb($hue, $saturation, $value)
99
    {
100
        // Lightness: 0.0 - 1.0
101
        $lightness = $this->sanitizeHsvValue($value, 0, 100) / 100.0;
102
        // Chroma:    0.0 - 1.0
103
        $chroma    = $lightness * ($this->sanitizeHsvValue($saturation, 0, 100) / 100.0);
104
105
        return array_map(function ($color) use ($lightness, $chroma) {
106
            return (int) round(($color + ($lightness - $chroma)) * 255);
107
        }, $this->calculateRgbWithHueAndChroma($hue, $chroma));
108
    }
109
110
    /* ------------------------------------------------------------------------------------------------
111
     |  Other Functions
112
     | ------------------------------------------------------------------------------------------------
113
     */
114
    /**
115
     * Calculate RGB with hue and chroma.
116
     *
117
     * @param  float|int  $hue
118
     * @param  float|int  $chroma
119
     *
120
     * @return array
121
     */
122
    protected function calculateRgbWithHueAndChroma($hue, $chroma)
123
    {
124
        $hPrime = $this->sanitizeHsvValue($hue, 0, 360) / 60.0;
125
        $xPrime = $this->calculateXPrime($hPrime, $chroma);
126
127
        switch (floor($hPrime)) {
128
            case 0:  return [$chroma, $xPrime, 0.0];
129
            case 1:  return [$xPrime, $chroma, 0.0];
130
            case 2:  return [0.0, $chroma, $xPrime];
131
            case 3:  return [0.0, $xPrime, $chroma];
132
            case 4:  return [$xPrime, 0.0, $chroma];
133
            case 5:  return [$chroma, 0.0, $xPrime];
134
            default: return [0.0, 0.0, 0.0];
135
        }
136
    }
137
138
    /**
139
     * Calculate X-Prime.
140
     *
141
     * @param  float|int  $hPrime
142
     * @param  float|int  $chroma
143
     *
144
     * @return float|int
145
     */
146
    protected function calculateXPrime($hPrime, $chroma)
147
    {
148
        while ($hPrime >= 2.0) $hPrime -= 2.0;
149
150
        return $chroma * (1 - abs($hPrime - 1));
151
    }
152
153
    /**
154
     * Sanitize HSV value.
155
     *
156
     * @param  int  $value
157
     * @param  int  $min
158
     * @param  int  $max
159
     *
160
     * @return float|int
161
     */
162
    protected function sanitizeHsvValue($value, $min, $max)
163
    {
164
        if ($value < $min) return $min;
165
        if ($value > $max) return $max;
166
167
        return $value;
168
    }
169
}
170