|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
|
|
4
|
|
|
namespace projectcleverweb\color; |
|
5
|
|
|
|
|
6
|
|
|
|
|
7
|
|
|
class generate { |
|
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
|
1 |
|
public static function rgb_contrast(int $r = 0, int $g = 0, int $b = 0) :array { |
|
63
|
|
|
return [ |
|
64
|
1 |
|
'r' => ($r < 128) ? 255 : 0, |
|
65
|
1 |
|
'g' => ($g < 128) ? 255 : 0, |
|
66
|
1 |
|
'b' => ($b < 128) ? 255 : 0 |
|
67
|
|
|
]; |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
1 |
|
public static function rgb_invert(int $r = 0, int $g = 0, int $b = 0) :array { |
|
71
|
|
|
return [ |
|
72
|
1 |
|
'r' => 255 - $r, |
|
73
|
1 |
|
'g' => 255 - $g, |
|
74
|
1 |
|
'b' => 255 - $b |
|
75
|
|
|
]; |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
2 |
|
public static function yiq_score(int $r = 0, int $g = 0, int $b = 0) :float { |
|
79
|
2 |
|
return (($r * 299) + ($g * 587) + ($b * 114)) / 1000; |
|
80
|
|
|
} |
|
81
|
|
|
|
|
82
|
1 |
|
public static function rand(int $min_r = 0, int $max_r = 255, int $min_g = 0, int $max_g = 255, int $min_b = 0, int $max_b = 255) :array { |
|
83
|
|
|
return [ |
|
84
|
1 |
|
'r' => rand(abs((int) $min_r) % 256, abs((int) $max_r) % 256), |
|
85
|
1 |
|
'g' => rand(abs((int) $min_g) % 256, abs((int) $max_g) % 256), |
|
86
|
1 |
|
'b' => rand(abs((int) $min_b) % 256, abs((int) $max_b) % 256) |
|
87
|
|
|
]; |
|
88
|
|
|
} |
|
89
|
|
|
|
|
90
|
|
|
|
|
91
|
2 |
|
public static function rgb_to_hsl(int $r = 0, int $g = 0, int $b = 0, $accuracy = 2) :array { |
|
92
|
2 |
|
$r /= 255; |
|
93
|
2 |
|
$g /= 255; |
|
94
|
2 |
|
$b /= 255; |
|
95
|
2 |
|
$min = min($r, $g, $b); |
|
96
|
2 |
|
$max = max($r, $g, $b); |
|
97
|
2 |
|
$delta = $max - $min; |
|
98
|
2 |
|
$h = 0; |
|
99
|
2 |
|
$s = 0; |
|
100
|
2 |
|
$l = ($max + $min) / 2; |
|
101
|
|
|
|
|
102
|
2 |
|
if ($delta != 0) { |
|
103
|
2 |
|
$s = $delta / ($max + $min); |
|
104
|
2 |
|
if ($l >= 0.5) { |
|
105
|
2 |
|
$s = $delta / (2 - $max - $min); |
|
106
|
|
|
} |
|
107
|
2 |
|
static::_rgbhsl_hue($h, $r, $g, $b, $max, $delta); |
|
108
|
|
|
} |
|
109
|
|
|
|
|
110
|
|
|
return [ |
|
111
|
2 |
|
'h' => round($h * 360, $accuracy), |
|
112
|
2 |
|
's' => round($s * 100, $accuracy), |
|
113
|
2 |
|
'l' => round($l * 100, $accuracy) |
|
114
|
|
|
]; |
|
115
|
|
|
} |
|
116
|
|
|
|
|
117
|
2 |
|
protected static function _rgbhsl_delta_rgb(float $rgb, float $max, float $delta) { |
|
118
|
2 |
|
return ((($max - $rgb) / 6) + ($delta / 2)) / $delta; |
|
119
|
|
|
} |
|
120
|
|
|
|
|
121
|
2 |
|
protected static function _rgbhsl_hue(float &$h, float $r, float $g, float $b, float $max, float $delta) { |
|
122
|
2 |
|
$delta_r = static::_rgbhsl_delta_rgb($r, $max, $delta); |
|
123
|
2 |
|
$delta_g = static::_rgbhsl_delta_rgb($g, $max, $delta); |
|
124
|
2 |
|
$delta_b = static::_rgbhsl_delta_rgb($b, $max, $delta); |
|
125
|
|
|
|
|
126
|
2 |
|
$h = (2 / 3) + $delta_g - $delta_r; |
|
127
|
2 |
|
if ($r == $max) { |
|
128
|
2 |
|
$h = $delta_b - $delta_g; |
|
129
|
2 |
|
} elseif ($g == $max) { |
|
130
|
2 |
|
$h = (1 / 3) + $delta_r - $delta_b; |
|
131
|
|
|
} |
|
132
|
2 |
|
if ($h < 0) { |
|
133
|
2 |
|
$h++; |
|
134
|
|
|
} |
|
135
|
2 |
|
} |
|
136
|
|
|
|
|
137
|
2 |
|
public static function hsl_to_rgb(float $h = 0, float $s = 0, float $l = 0) :array { |
|
138
|
2 |
|
$s /= 100; |
|
139
|
2 |
|
$l /= 100; |
|
140
|
2 |
|
$c = (1 - abs((2 * $l) - 1)) * $s; |
|
141
|
2 |
|
$x = $c * (1 - abs(fmod(($h / 60), 2) - 1)); |
|
142
|
2 |
|
$m = $l - ($c / 2); |
|
143
|
2 |
|
$r = $c; |
|
144
|
2 |
|
$g = 0; |
|
145
|
2 |
|
$b = $x; |
|
146
|
|
|
|
|
147
|
2 |
|
if ($h < 180) { |
|
148
|
2 |
|
self::_hslrgb_low($r, $g, $b, $c, $x, $h); |
|
149
|
2 |
|
} elseif ($h < 300) { |
|
150
|
2 |
|
self::_hslrgb_high($r, $g, $b, $c, $x, $h); |
|
151
|
|
|
} |
|
152
|
|
|
|
|
153
|
|
|
return [ |
|
154
|
2 |
|
'r' => (int) round(($r + $m) * 255), |
|
155
|
2 |
|
'g' => (int) round(($g + $m) * 255), |
|
156
|
2 |
|
'b' => (int) round(($b + $m) * 255) |
|
157
|
|
|
]; |
|
158
|
|
|
} |
|
159
|
|
|
|
|
160
|
2 |
|
private static function _hslrgb_low(float &$r, float &$g, float &$b, float $c, float $x, float $h) { |
|
161
|
2 |
|
if ($h < 60) { |
|
162
|
2 |
|
$r = $c; |
|
163
|
2 |
|
$g = $x; |
|
164
|
2 |
|
$b = 0; |
|
165
|
2 |
|
} elseif ($h < 120) { |
|
166
|
2 |
|
$r = $x; |
|
167
|
2 |
|
$g = $c; |
|
168
|
2 |
|
$b = 0; |
|
169
|
2 |
|
} elseif ($h < 180) { |
|
170
|
2 |
|
$r = 0; |
|
171
|
2 |
|
$g = $c; |
|
172
|
2 |
|
$b = $x; |
|
173
|
|
|
} |
|
174
|
2 |
|
} |
|
175
|
|
|
|
|
176
|
2 |
|
private static function _hslrgb_high(float &$r, float &$g, float &$b, float $c, float $x, float $h) { |
|
177
|
2 |
|
if ($h < 240) { |
|
178
|
2 |
|
$r = 0; |
|
179
|
2 |
|
$g = $x; |
|
180
|
2 |
|
$b = $c; |
|
181
|
2 |
|
} elseif ($h < 300) { |
|
182
|
2 |
|
$r = $x; |
|
183
|
2 |
|
$g = 0; |
|
184
|
2 |
|
$b = $c; |
|
185
|
|
|
} |
|
186
|
2 |
|
} |
|
187
|
|
|
|
|
188
|
1 |
|
public static function rgb_to_hsb(float $r, float $g, float $b, int $accuracy = 3) { |
|
189
|
1 |
|
$r /= 255; |
|
190
|
1 |
|
$g /= 255; |
|
191
|
1 |
|
$b /= 255; |
|
192
|
|
|
|
|
193
|
1 |
|
$max = max($r, $g, $b); |
|
194
|
1 |
|
$min = min($r, $g, $b); |
|
195
|
1 |
|
$v = $max; |
|
|
|
|
|
|
196
|
|
|
|
|
197
|
1 |
|
$d = $max - $min; |
|
198
|
1 |
|
$s = $max == 0 ? 0 : $d / $max; |
|
199
|
|
|
|
|
200
|
1 |
|
$h = 0; // achromatic |
|
201
|
1 |
|
if ($max !== $min) { |
|
202
|
|
|
switch ($max) { |
|
203
|
1 |
|
case $r: $h = ($g - $b) / $d + ($g < $b ? 6 : 0); break; |
|
|
|
|
|
|
204
|
1 |
|
case $g: $h = ($b - $r) / $d + 2; break; |
|
|
|
|
|
|
205
|
1 |
|
case $b: $h = ($r - $g) / $d + 4; break; |
|
|
|
|
|
|
206
|
|
|
} |
|
207
|
1 |
|
$h /= 6; |
|
208
|
|
|
} |
|
209
|
|
|
// map top 360,100,100 |
|
|
|
|
|
|
210
|
1 |
|
$h = round($h * 360, $accuracy); |
|
211
|
1 |
|
$s = round($s * 100, $accuracy); |
|
212
|
1 |
|
$v = round($v * 100, $accuracy); |
|
213
|
|
|
|
|
214
|
1 |
|
return ['h' => $h, 's' => $s, 'b' => $v]; |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
1 |
|
public static function hsb_to_rgb(float $h, float $s, float $v, int $accuracy = 3) { |
|
218
|
|
|
// $h = $h / 360; |
|
|
|
|
|
|
219
|
1 |
|
if ($v == 0) { |
|
220
|
1 |
|
return ['r' => 0, 'g' => 0, 'b' => 0]; |
|
221
|
|
|
} |
|
222
|
|
|
|
|
223
|
1 |
|
$s = $s / 100; |
|
224
|
1 |
|
$v = $v / 100; |
|
225
|
1 |
|
$h = $h / 60; |
|
226
|
|
|
|
|
227
|
1 |
|
$i = floor($h); |
|
228
|
1 |
|
$f = $h - $i; |
|
229
|
1 |
|
$p = $v * (1 - $s); |
|
230
|
1 |
|
$q = $v * (1 - ($s * $f)); |
|
231
|
1 |
|
$t = $v * (1 - ($s * (1 - $f))); |
|
232
|
1 |
|
if ($i == 0) { |
|
233
|
1 |
|
$r = $v; $g = $t; $b = $p; |
|
|
|
|
|
|
234
|
1 |
|
} elseif ($i == 1) { |
|
235
|
1 |
|
$r = $q; $g = $v; $b = $p; |
|
|
|
|
|
|
236
|
1 |
|
} elseif ($i == 2) { |
|
237
|
1 |
|
$r = $p; $g = $v; $b = $t; |
|
|
|
|
|
|
238
|
1 |
|
} elseif ($i == 3) { |
|
239
|
1 |
|
$r = $p; $g = $q; $b = $v; |
|
|
|
|
|
|
240
|
1 |
|
} elseif ($i == 4) { |
|
241
|
1 |
|
$r = $t; $g = $p; $b = $v; |
|
|
|
|
|
|
242
|
1 |
|
} elseif ($i == 5) { |
|
243
|
1 |
|
$r = $v; $g = $p; $b = $q; |
|
|
|
|
|
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
1 |
|
$r = round($r * 255, $accuracy); |
|
|
|
|
|
|
247
|
1 |
|
$g = round($g * 255, $accuracy); |
|
|
|
|
|
|
248
|
1 |
|
$b = round($b * 255, $accuracy); |
|
|
|
|
|
|
249
|
|
|
|
|
250
|
1 |
|
return ['r' => $r, 'g' => $g, 'b' => $b]; |
|
251
|
|
|
} |
|
252
|
|
|
|
|
253
|
|
|
|
|
254
|
|
|
|
|
255
|
|
|
|
|
256
|
|
|
|
|
257
|
|
|
} |
|
258
|
|
|
|
This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.
To visualize
will produce issues in the first and second line, while this second example
will produce no issues.