]> git.mxchange.org Git - friendica.git/blob - view/theme/frio/php/PHPColors/Color.php
Revert "Coding convention applied - part 1"
[friendica.git] / view / theme / frio / php / PHPColors / Color.php
1 <?php
2
3 /**
4  * Author: Arlo Carreon <http://arlocarreon.com>
5  * Info: http://mexitek.github.io/phpColors/
6  * License: http://arlo.mit-license.org/
7  */
8
9
10 /**
11  * A color utility that helps manipulate HEX colors
12  */
13 class Color {
14
15     private $_hex;
16     private $_hsl;
17     private $_rgb;
18
19     /**
20      * Auto darkens/lightens by 10% for sexily-subtle gradients.
21      * Set this to FALSE to adjust automatic shade to be between given color
22      * and black (for darken) or white (for lighten)
23      */
24     const DEFAULT_ADJUST = 10;
25
26     /**
27      * Instantiates the class with a HEX value
28      * @param string $hex
29      * @throws Exception "Bad color format"
30      */
31     function __construct( $hex ) {
32         // Strip # sign is present
33         $color = str_replace("#", "", $hex);
34
35         // Make sure it's 6 digits
36         if( strlen($color) === 3 ) {
37             $color = $color[0].$color[0].$color[1].$color[1].$color[2].$color[2];
38         } else if( strlen($color) != 6 ) {
39             throw new Exception("HEX color needs to be 6 or 3 digits long");
40         }
41
42         $this->_hsl = self::hexToHsl( $color );
43         $this->_hex = $color;
44         $this->_rgb = self::hexToRgb( $color );
45     }
46
47     // ====================
48     // = Public Interface =
49     // ====================
50
51     /**
52      * Given a HEX string returns a HSL array equivalent.
53      * @param string $color
54      * @return array HSL associative array
55      */
56     public static function hexToHsl( $color ){
57
58         // Sanity check
59         $color = self::_checkHex($color);
60
61         // Convert HEX to DEC
62         $R = hexdec($color[0].$color[1]);
63         $G = hexdec($color[2].$color[3]);
64         $B = hexdec($color[4].$color[5]);
65
66         $HSL = array();
67
68         $var_R = ($R / 255);
69         $var_G = ($G / 255);
70         $var_B = ($B / 255);
71
72         $var_Min = min($var_R, $var_G, $var_B);
73         $var_Max = max($var_R, $var_G, $var_B);
74         $del_Max = $var_Max - $var_Min;
75
76         $L = ($var_Max + $var_Min)/2;
77
78         if ($del_Max == 0)
79         {
80             $H = 0;
81             $S = 0;
82         }
83         else
84         {
85             if ( $L < 0.5 ) $S = $del_Max / ( $var_Max + $var_Min );
86             else            $S = $del_Max / ( 2 - $var_Max - $var_Min );
87
88             $del_R = ( ( ( $var_Max - $var_R ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
89             $del_G = ( ( ( $var_Max - $var_G ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
90             $del_B = ( ( ( $var_Max - $var_B ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
91
92             if      ($var_R == $var_Max) $H = $del_B - $del_G;
93             else if ($var_G == $var_Max) $H = ( 1 / 3 ) + $del_R - $del_B;
94             else if ($var_B == $var_Max) $H = ( 2 / 3 ) + $del_G - $del_R;
95
96             if ($H<0) $H++;
97             if ($H>1) $H--;
98         }
99
100         $HSL['H'] = ($H*360);
101         $HSL['S'] = $S;
102         $HSL['L'] = $L;
103
104         return $HSL;
105     }
106
107     /**
108      *  Given a HSL associative array returns the equivalent HEX string
109      * @param array $hsl
110      * @return string HEX string
111      * @throws Exception "Bad HSL Array"
112      */
113     public static function hslToHex( $hsl = array() ){
114          // Make sure it's HSL
115         if(empty($hsl) || !isset($hsl["H"]) || !isset($hsl["S"]) || !isset($hsl["L"]) ) {
116             throw new Exception("Param was not an HSL array");
117         }
118
119         list($H,$S,$L) = array( $hsl['H']/360,$hsl['S'],$hsl['L'] );
120
121         if( $S == 0 ) {
122             $r = $L * 255;
123             $g = $L * 255;
124             $b = $L * 255;
125         } else {
126
127             if($L<0.5) {
128                 $var_2 = $L*(1+$S);
129             } else {
130                 $var_2 = ($L+$S) - ($S*$L);
131             }
132
133             $var_1 = 2 * $L - $var_2;
134
135             $r = round(255 * self::_huetorgb( $var_1, $var_2, $H + (1/3) ));
136             $g = round(255 * self::_huetorgb( $var_1, $var_2, $H ));
137             $b = round(255 * self::_huetorgb( $var_1, $var_2, $H - (1/3) ));
138
139         }
140
141         // Convert to hex
142         $r = dechex($r);
143         $g = dechex($g);
144         $b = dechex($b);
145
146         // Make sure we get 2 digits for decimals
147         $r = (strlen("".$r)===1) ? "0".$r:$r;
148         $g = (strlen("".$g)===1) ? "0".$g:$g;
149         $b = (strlen("".$b)===1) ? "0".$b:$b;
150
151         return $r.$g.$b;
152     }
153
154
155     /**
156      * Given a HEX string returns a RGB array equivalent.
157      * @param string $color
158      * @return array RGB associative array
159      */
160     public static function hexToRgb( $color ){
161
162         // Sanity check
163         $color = self::_checkHex($color);
164
165         // Convert HEX to DEC
166         $R = hexdec($color[0].$color[1]);
167         $G = hexdec($color[2].$color[3]);
168         $B = hexdec($color[4].$color[5]);
169
170         $RGB['R'] = $R;
171         $RGB['G'] = $G;
172         $RGB['B'] = $B;
173
174         return $RGB;
175     }
176
177
178     /**
179      *  Given an RGB associative array returns the equivalent HEX string
180      * @param array $rgb
181      * @return string RGB string
182      * @throws Exception "Bad RGB Array"
183      */
184     public static function rgbToHex( $rgb = array() ){
185          // Make sure it's RGB
186         if(empty($rgb) || !isset($rgb["R"]) || !isset($rgb["G"]) || !isset($rgb["B"]) ) {
187             throw new Exception("Param was not an RGB array");
188         }
189
190         // https://github.com/mexitek/phpColors/issues/25#issuecomment-88354815
191         // Convert RGB to HEX
192         $hex[0] = str_pad(dechex($rgb['R']), 2, '0', STR_PAD_LEFT);
193         $hex[1] = str_pad(dechex($rgb['G']), 2, '0', STR_PAD_LEFT);
194         $hex[2] = str_pad(dechex($rgb['B']), 2, '0', STR_PAD_LEFT);
195
196         return implode( '', $hex );
197
198   }
199
200
201     /**
202      * Given a HEX value, returns a darker color. If no desired amount provided, then the color halfway between
203      * given HEX and black will be returned.
204      * @param int $amount
205      * @return string Darker HEX value
206      */
207     public function darken( $amount = self::DEFAULT_ADJUST ){
208         // Darken
209         $darkerHSL = $this->_darken($this->_hsl, $amount);
210         // Return as HEX
211         return self::hslToHex($darkerHSL);
212     }
213
214     /**
215      * Given a HEX value, returns a lighter color. If no desired amount provided, then the color halfway between
216      * given HEX and white will be returned.
217      * @param int $amount
218      * @return string Lighter HEX value
219      */
220     public function lighten( $amount = self::DEFAULT_ADJUST ){
221         // Lighten
222         $lighterHSL = $this->_lighten($this->_hsl, $amount);
223         // Return as HEX
224         return self::hslToHex($lighterHSL);
225     }
226
227     /**
228      * Given a HEX value, returns a mixed color. If no desired amount provided, then the color mixed by this ratio
229      * @param string $hex2 Secondary HEX value to mix with
230      * @param int $amount = -100..0..+100
231      * @return string mixed HEX value
232      */
233     public function mix($hex2, $amount = 0){
234         $rgb2 = self::hexToRgb($hex2);
235         $mixed = $this->_mix($this->_rgb, $rgb2, $amount);
236         // Return as HEX
237         return self::rgbToHex($mixed);
238     }
239
240     /**
241      * Creates an array with two shades that can be used to make a gradient
242      * @param int $amount Optional percentage amount you want your contrast color
243      * @return array An array with a 'light' and 'dark' index
244      */
245     public function makeGradient( $amount = self::DEFAULT_ADJUST ) {
246         // Decide which color needs to be made
247         if( $this->isLight() ) {
248             $lightColor = $this->_hex;
249             $darkColor = $this->darken($amount);
250         } else {
251             $lightColor = $this->lighten($amount);
252             $darkColor = $this->_hex;
253         }
254
255         // Return our gradient array
256         return array( "light" => $lightColor, "dark" => $darkColor );
257     }
258
259
260     /**
261      * Returns whether or not given color is considered "light"
262      * @param string|Boolean $color
263      * @param int $lighterThan
264      * @return boolean
265      */
266     public function isLight( $color = FALSE, $lighterThan = 130 ){
267         // Get our color
268         $color = ($color) ? $color : $this->_hex;
269
270         // Calculate straight from rbg
271         $r = hexdec($color[0].$color[1]);
272         $g = hexdec($color[2].$color[3]);
273         $b = hexdec($color[4].$color[5]);
274
275         return (( $r*299 + $g*587 + $b*114 )/1000 > $lighterThan);
276     }
277
278     /**
279      * Returns whether or not a given color is considered "dark"
280      * @param string|Boolean $color
281      * @param int $darkerThan
282      * @return boolean
283      */
284     public function isDark( $color = FALSE, $darkerThan = 130 ){
285         // Get our color
286         $color = ($color) ? $color:$this->_hex;
287
288         // Calculate straight from rbg
289         $r = hexdec($color[0].$color[1]);
290         $g = hexdec($color[2].$color[3]);
291         $b = hexdec($color[4].$color[5]);
292
293         return (( $r*299 + $g*587 + $b*114 )/1000 <= $darkerThan);
294     }
295
296     /**
297      * Returns the complimentary color
298      * @return string Complementary hex color
299      *
300      */
301     public function complementary() {
302         // Get our HSL
303         $hsl = $this->_hsl;
304
305         // Adjust Hue 180 degrees
306         $hsl['H'] += ($hsl['H']>180) ? -180:180;
307
308         // Return the new value in HEX
309         return self::hslToHex($hsl);
310     }
311     
312     /**
313      * Returns your color's HSL array
314      */
315     public function getHsl() {
316         return $this->_hsl;
317     }
318     /**
319      * Returns your original color
320      */
321     public function getHex() {
322         return $this->_hex;
323     }
324     /**
325      * Returns your color's RGB array
326      */
327     public function getRgb() {
328         return $this->_rgb;
329     }
330     
331     /**
332      * Returns the cross browser CSS3 gradient
333      * @param int $amount Optional: percentage amount to light/darken the gradient
334      * @param boolean $vintageBrowsers Optional: include vendor prefixes for browsers that almost died out already
335      * @param string $prefix Optional: prefix for every lines
336      * @param string $suffix Optional: suffix for every lines
337      * @link  http://caniuse.com/css-gradients Resource for the browser support
338      * @return string CSS3 gradient for chrome, safari, firefox, opera and IE10
339      */
340     public function getCssGradient( $amount = self::DEFAULT_ADJUST, $vintageBrowsers = FALSE, $suffix = "" , $prefix = "" ) {
341
342         // Get the recommended gradient
343         $g = $this->makeGradient($amount);
344
345         $css = "";
346         /* fallback/image non-cover color */
347         $css .= "{$prefix}background-color: #".$this->_hex.";{$suffix}";
348
349         /* IE Browsers */
350         $css .= "{$prefix}filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#".$g['light']."', endColorstr='#".$g['dark']."');{$suffix}";
351
352         /* Safari 4+, Chrome 1-9 */
353         if ( $vintageBrowsers ) {
354             $css .= "{$prefix}background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#".$g['light']."), to(#".$g['dark']."));{$suffix}";
355         }
356
357         /* Safari 5.1+, Mobile Safari, Chrome 10+ */
358         $css .= "{$prefix}background-image: -webkit-linear-gradient(top, #".$g['light'].", #".$g['dark'].");{$suffix}";
359
360         /* Firefox 3.6+ */
361         if ( $vintageBrowsers ) {
362             $css .= "{$prefix}background-image: -moz-linear-gradient(top, #".$g['light'].", #".$g['dark'].");{$suffix}";
363         }
364
365         /* Opera 11.10+ */
366         if ( $vintageBrowsers ) {
367             $css .= "{$prefix}background-image: -o-linear-gradient(top, #".$g['light'].", #".$g['dark'].");{$suffix}";
368         }
369
370         /* Unprefixed version (standards): FF 16+, IE10+, Chrome 26+, Safari 7+, Opera 12.1+ */
371         $css .= "{$prefix}background-image: linear-gradient(to bottom, #".$g['light'].", #".$g['dark'].");{$suffix}";
372
373         // Return our CSS
374         return $css;
375     }
376
377     // ===========================
378     // = Private Functions Below =
379     // ===========================
380
381
382     /**
383      * Darkens a given HSL array
384      * @param array $hsl
385      * @param int $amount
386      * @return array $hsl
387      */
388     private function _darken( $hsl, $amount = self::DEFAULT_ADJUST){
389         // Check if we were provided a number
390         if( $amount ) {
391             $hsl['L'] = ($hsl['L'] * 100) - $amount;
392             $hsl['L'] = ($hsl['L'] < 0) ? 0:$hsl['L']/100;
393         } else {
394             // We need to find out how much to darken
395             $hsl['L'] = $hsl['L']/2 ;
396         }
397
398         return $hsl;
399     }
400
401     /**
402      * Lightens a given HSL array
403      * @param array $hsl
404      * @param int $amount
405      * @return array $hsl
406      */
407     private function _lighten( $hsl, $amount = self::DEFAULT_ADJUST){
408         // Check if we were provided a number
409         if( $amount ) {
410             $hsl['L'] = ($hsl['L'] * 100) + $amount;
411             $hsl['L'] = ($hsl['L'] > 100) ? 1:$hsl['L']/100;
412         } else {
413             // We need to find out how much to lighten
414             $hsl['L'] += (1-$hsl['L'])/2;
415         }
416
417         return $hsl;
418     }
419
420     /**
421      * Mix 2 rgb colors and return an rgb color
422      * @param array $rgb1
423      * @param array $rgb2
424      * @param int $amount ranged -100..0..+100
425      * @return array $rgb
426      *
427      *  ported from http://phpxref.pagelines.com/nav.html?includes/class.colors.php.source.html
428      */
429     private function _mix($rgb1, $rgb2, $amount = 0) {
430
431          $r1 = ($amount + 100) / 100;
432          $r2 = 2 - $r1;
433
434          $rmix = (($rgb1['R'] * $r1) + ($rgb2['R'] * $r2)) / 2;
435          $gmix = (($rgb1['G'] * $r1) + ($rgb2['G'] * $r2)) / 2;
436          $bmix = (($rgb1['B'] * $r1) + ($rgb2['B'] * $r2)) / 2;
437
438          return array('R' => $rmix, 'G' => $gmix, 'B' => $bmix);
439      }
440
441     /**
442      * Given a Hue, returns corresponding RGB value
443      * @param int $v1
444      * @param int $v2
445      * @param int $vH
446      * @return int
447      */
448     private static function _huetorgb( $v1,$v2,$vH ) {
449         if( $vH < 0 ) {
450             $vH += 1;
451         }
452
453         if( $vH > 1 ) {
454             $vH -= 1;
455         }
456
457         if( (6*$vH) < 1 ) {
458                return ($v1 + ($v2 - $v1) * 6 * $vH);
459         }
460
461         if( (2*$vH) < 1 ) {
462             return $v2;
463         }
464
465         if( (3*$vH) < 2 ) {
466             return ($v1 + ($v2-$v1) * ( (2/3)-$vH ) * 6);
467         }
468
469         return $v1;
470
471     }
472
473     /**
474      * You need to check if you were given a good hex string
475      * @param string $hex
476      * @return string Color
477      * @throws Exception "Bad color format"
478      */
479     private static function _checkHex( $hex ) {
480         // Strip # sign is present
481         $color = str_replace("#", "", $hex);
482
483         // Make sure it's 6 digits
484         if( strlen($color) == 3 ) {
485             $color = $color[0].$color[0].$color[1].$color[1].$color[2].$color[2];
486         } else if( strlen($color) != 6 ) {
487             throw new Exception("HEX color needs to be 6 or 3 digits long");
488         }
489
490         return $color;
491     }
492
493 }