|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
|
|
4
|
|
|
namespace projectcleverweb\color; |
|
5
|
|
|
|
|
6
|
|
|
|
|
7
|
|
|
class convert { |
|
8
|
|
|
|
|
9
|
|
|
/** |
|
10
|
|
|
* Convert a hex string (no #) to a RGB array |
|
11
|
|
|
* |
|
12
|
|
|
* @param string $hex The hex string to convert (no #) |
|
13
|
|
|
* @return array The RGB array |
|
14
|
|
|
*/ |
|
15
|
1 |
|
public static function hex_to_rgb(string $hex) :array { |
|
16
|
|
|
return [ |
|
17
|
1 |
|
'r' => hexdec(substr($hex, 0, 2)), |
|
18
|
1 |
|
'g' => hexdec(substr($hex, 2, 2)), |
|
19
|
1 |
|
'b' => hexdec(substr($hex, 4, 2)) |
|
20
|
|
|
]; |
|
21
|
|
|
} |
|
22
|
|
|
|
|
23
|
1 |
|
public static function rgb_to_hex(int $r, int $g, int $b) :string { |
|
24
|
1 |
|
return strtoupper( |
|
25
|
1 |
|
str_pad(dechex($r), 2, '0', STR_PAD_LEFT) |
|
26
|
1 |
|
.str_pad(dechex($g), 2, '0', STR_PAD_LEFT) |
|
27
|
1 |
|
.str_pad(dechex($b), 2, '0', STR_PAD_LEFT) |
|
28
|
|
|
); |
|
29
|
|
|
} |
|
30
|
|
|
|
|
31
|
1 |
|
public static function rgb_to_cmyk(float $r, float $g, float $b) :array { |
|
32
|
1 |
|
$c = (255 - $r) / 255 * 100; |
|
33
|
1 |
|
$m = (255 - $g) / 255 * 100; |
|
34
|
1 |
|
$y = (255 - $b) / 255 * 100; |
|
35
|
1 |
|
$k = min(array($c,$m,$y)); |
|
36
|
1 |
|
$c -= $k; |
|
37
|
1 |
|
$m -= $k; |
|
38
|
1 |
|
$y -= $k; |
|
39
|
|
|
return [ |
|
40
|
1 |
|
'c' => round($c), |
|
41
|
1 |
|
'm' => round($m), |
|
42
|
1 |
|
'y' => round($y), |
|
43
|
1 |
|
'k' => round($k) |
|
44
|
|
|
]; |
|
45
|
|
|
} |
|
46
|
|
|
|
|
47
|
1 |
|
public static function cmyk_to_rgb(float $c, float $m, float $y, float $k) :array { |
|
48
|
1 |
|
$c /= 100; |
|
49
|
1 |
|
$m /= 100; |
|
50
|
1 |
|
$y /= 100; |
|
51
|
1 |
|
$k /= 100; |
|
52
|
1 |
|
$r = 1 - min(1, $c * (1 - $k) + $k); |
|
53
|
1 |
|
$g = 1 - min(1, $m * (1 - $k) + $k); |
|
54
|
1 |
|
$b = 1 - min(1, $y * (1 - $k) + $k); |
|
55
|
|
|
return [ |
|
56
|
1 |
|
'r' => round($r * 255), |
|
57
|
1 |
|
'g' => round($g * 255), |
|
58
|
1 |
|
'b' => round($b * 255) |
|
59
|
|
|
]; |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
View Code Duplication |
public static function rgb_contrast(int $r = 0, int $g = 0, int $b = 0) :array { |
|
|
|
|
|
|
63
|
|
|
return [ |
|
64
|
|
|
'r' => ($r < 128) ? 255 : 0, |
|
65
|
|
|
'g' => ($g < 128) ? 255 : 0, |
|
66
|
|
|
'b' => ($b < 128) ? 255 : 0 |
|
67
|
|
|
]; |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
2 |
|
public static function rgb_to_hsl(int $r = 0, int $g = 0, int $b = 0, $accuracy = 2) :array { |
|
71
|
2 |
|
$r /= 255; |
|
72
|
2 |
|
$g /= 255; |
|
73
|
2 |
|
$b /= 255; |
|
74
|
2 |
|
$min = min($r, $g, $b); |
|
75
|
2 |
|
$max = max($r, $g, $b); |
|
76
|
2 |
|
$delta = $max - $min; |
|
77
|
2 |
|
$h = 0; |
|
78
|
2 |
|
$s = 0; |
|
79
|
2 |
|
$l = ($max + $min) / 2; |
|
80
|
|
|
|
|
81
|
2 |
|
if ($max != $min) { |
|
82
|
2 |
|
$s = $delta / ($max + $min); |
|
83
|
2 |
|
if ($l >= 0.5) { |
|
84
|
2 |
|
$s = $delta / (2 - $max - $min); |
|
85
|
|
|
} |
|
86
|
2 |
|
static::_rgbhsl_hue($h, $r, $g, $b, $max, $delta); |
|
87
|
|
|
} |
|
88
|
|
|
|
|
89
|
|
|
return [ |
|
90
|
2 |
|
'h' => round($h * 360, $accuracy), |
|
91
|
2 |
|
's' => round($s * 100, $accuracy), |
|
92
|
2 |
|
'l' => round($l * 100, $accuracy) |
|
93
|
|
|
]; |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
3 |
|
protected static function _rgbhsl_delta_rgb(float $rgb, float $max, float $delta) { |
|
97
|
3 |
|
return ((($max - $rgb) / 6) + ($delta / 2)) / $delta; |
|
98
|
|
|
} |
|
99
|
|
|
|
|
100
|
3 |
|
protected static function _rgbhsl_hue(float &$h, float $r, float $g, float $b, float $max, float $delta) { |
|
101
|
3 |
|
$delta_r = static::_rgbhsl_delta_rgb($r, $max, $delta); |
|
102
|
3 |
|
$delta_g = static::_rgbhsl_delta_rgb($g, $max, $delta); |
|
103
|
3 |
|
$delta_b = static::_rgbhsl_delta_rgb($b, $max, $delta); |
|
104
|
|
|
|
|
105
|
3 |
|
$h = (2 / 3) + $delta_g - $delta_r; |
|
106
|
3 |
|
if ($r == $max) { |
|
107
|
3 |
|
$h = $delta_b - $delta_g; |
|
108
|
3 |
|
} elseif ($g == $max) { |
|
109
|
3 |
|
$h = (1 / 3) + $delta_r - $delta_b; |
|
110
|
|
|
} |
|
111
|
3 |
|
if ($h < 0) { |
|
112
|
3 |
|
$h++; |
|
113
|
|
|
} |
|
114
|
3 |
|
} |
|
115
|
|
|
|
|
116
|
2 |
|
public static function hsl_to_rgb(float $h = 0, float $s = 0, float $l = 0) :array { |
|
117
|
2 |
|
$s /= 100; |
|
118
|
2 |
|
$l /= 100; |
|
119
|
2 |
|
$c = (1 - abs((2 * $l) - 1)) * $s; |
|
120
|
2 |
|
$x = $c * (1 - abs(fmod(($h / 60), 2) - 1)); |
|
121
|
2 |
|
$m = $l - ($c / 2); |
|
122
|
2 |
|
$r = $c; |
|
123
|
2 |
|
$g = 0; |
|
124
|
2 |
|
$b = $x; |
|
125
|
|
|
|
|
126
|
2 |
|
if ($h < 180) { |
|
127
|
2 |
|
self::_hslrgb_low($r, $g, $b, $c, $x, $h); |
|
128
|
2 |
|
} elseif ($h < 300) { |
|
129
|
2 |
|
self::_hslrgb_high($r, $g, $b, $c, $x, $h); |
|
130
|
|
|
} |
|
131
|
|
|
|
|
132
|
|
|
return [ |
|
133
|
2 |
|
'r' => (int) round(($r + $m) * 255), |
|
134
|
2 |
|
'g' => (int) round(($g + $m) * 255), |
|
135
|
2 |
|
'b' => (int) round(($b + $m) * 255) |
|
136
|
|
|
]; |
|
137
|
|
|
} |
|
138
|
|
|
|
|
139
|
2 |
|
private static function _hslrgb_low(float &$r, float &$g, float &$b, float $c, float $x, float $h) { |
|
140
|
2 |
|
if ($h < 60) { |
|
141
|
2 |
|
$r = $c; |
|
142
|
2 |
|
$g = $x; |
|
143
|
2 |
|
$b = 0; |
|
144
|
2 |
|
} elseif ($h < 120) { |
|
145
|
2 |
|
$r = $x; |
|
146
|
2 |
|
$g = $c; |
|
147
|
2 |
|
$b = 0; |
|
148
|
2 |
|
} elseif ($h < 180) { |
|
149
|
2 |
|
$r = 0; |
|
150
|
2 |
|
$g = $c; |
|
151
|
2 |
|
$b = $x; |
|
152
|
|
|
} |
|
153
|
2 |
|
} |
|
154
|
|
|
|
|
155
|
2 |
|
private static function _hslrgb_high(float &$r, float &$g, float &$b, float $c, float $x, float $h) { |
|
156
|
2 |
|
if ($h < 240) { |
|
157
|
2 |
|
$r = 0; |
|
158
|
2 |
|
$g = $x; |
|
159
|
2 |
|
$b = $c; |
|
160
|
2 |
|
} elseif ($h < 300) { |
|
161
|
2 |
|
$r = $x; |
|
162
|
2 |
|
$g = 0; |
|
163
|
2 |
|
$b = $c; |
|
164
|
|
|
} |
|
165
|
2 |
|
} |
|
166
|
|
|
|
|
167
|
1 |
|
public static function rgb_to_hsb(float $r, float $g, float $b, int $accuracy = 3) :array { |
|
168
|
1 |
|
$r /= 255; |
|
169
|
1 |
|
$g /= 255; |
|
170
|
1 |
|
$b /= 255; |
|
171
|
|
|
|
|
172
|
1 |
|
$max = max($r, $g, $b); |
|
173
|
1 |
|
$min = min($r, $g, $b); |
|
174
|
1 |
|
$v = $max; |
|
175
|
1 |
|
$d = $max - $min; |
|
176
|
1 |
|
$s = static::_div($d, $max); |
|
177
|
1 |
|
$h = 0; // achromatic |
|
178
|
1 |
|
if ($max != $min) { |
|
179
|
1 |
|
static::_rgbhsl_hue($h, $r, $g, $b, $max, $d); |
|
180
|
|
|
} |
|
181
|
|
|
|
|
182
|
1 |
|
$h = round($h * 360, $accuracy); |
|
183
|
1 |
|
$s = round($s * 100, $accuracy); |
|
184
|
1 |
|
$v = round($v * 100, $accuracy); |
|
185
|
|
|
|
|
186
|
1 |
|
return ['h' => $h, 's' => $s, 'b' => $v]; |
|
187
|
|
|
} |
|
188
|
|
|
|
|
189
|
1 |
|
public static function hsb_to_rgb(float $h, float $s, float $v, int $accuracy = 3) :array { |
|
190
|
1 |
|
if ($v == 0) { |
|
191
|
1 |
|
return ['r' => 0, 'g' => 0, 'b' => 0]; |
|
192
|
|
|
} |
|
193
|
|
|
|
|
194
|
1 |
|
$s /= 100; |
|
195
|
1 |
|
$v /= 100; |
|
196
|
1 |
|
$h /= 60; |
|
197
|
1 |
|
$i = floor($h); |
|
198
|
1 |
|
$f = $h - $i; |
|
199
|
1 |
|
$p = $v * (1 - $s); |
|
200
|
1 |
|
$q = $v * (1 - ($s * $f)); |
|
201
|
1 |
|
$t = $v * (1 - ($s * (1 - $f))); |
|
202
|
|
|
$calc = [ |
|
203
|
1 |
|
[$v, $t, $p], |
|
204
|
1 |
|
[$q, $v, $p], |
|
205
|
1 |
|
[$p, $v, $t], |
|
206
|
1 |
|
[$p, $q, $v], |
|
207
|
1 |
|
[$t, $p, $v], |
|
208
|
1 |
|
[$v, $p, $q] |
|
209
|
|
|
]; |
|
210
|
|
|
|
|
211
|
1 |
|
$r = round($calc[$i][0] * 255, $accuracy); |
|
212
|
1 |
|
$g = round($calc[$i][1] * 255, $accuracy); |
|
213
|
1 |
|
$b = round($calc[$i][2] * 255, $accuracy); |
|
214
|
|
|
|
|
215
|
1 |
|
return ['r' => $r, 'g' => $g, 'b' => $b]; |
|
216
|
|
|
} |
|
217
|
|
|
|
|
218
|
1 |
|
public static function _div(float $number, float $divisor) { |
|
219
|
1 |
|
if ($divisor == 0) { |
|
220
|
1 |
|
return 0; |
|
221
|
|
|
} |
|
222
|
1 |
|
return $number / $divisor; |
|
223
|
|
|
} |
|
224
|
|
|
} |
|
225
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.