123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516 |
- <?php
- namespace Pen;
- /* phpcs:ignoreFile */
- /**
- * A color utility that helps manipulate HEX colors
- *
- * Author: Arlo Carreon <http://arlocarreon.com>
- * Info: http://mexitek.github.io/phpColors/
- * License: http://arlo.mit-license.org/
- */
- class Color {
- private $_hex;
- private $_hsl;
- private $_rgb;
- /**
- * Auto darkens/lightens by 10% for sexily-subtle gradients.
- * Set this to FALSE to adjust automatic shade to be between given color
- * and black (for darken) or white (for lighten)
- */
- const DEFAULT_ADJUST = 10;
- /**
- * Instantiates the class with a HEX value
- * @param string $hex
- * @throws Exception "Bad color format"
- */
- function __construct( $hex ) {
- // Strip # sign is present
- $color = str_replace( '#', '', $hex );
- // Make sure it's 6 digits
- if ( strlen( $color ) === 3 ) {
- $color = $color[0] . $color[0] . $color[1] . $color[1] . $color[2] . $color[2];
- } elseif ( strlen( $color ) != 6 ) {
- throw new Exception( esc_html__( 'HEX color needs to be 6 or 3 digits long', 'pen' ) );
- }
- $this->_hsl = self::hexToHsl( $color );
- $this->_hex = $color;
- $this->_rgb = self::hexToRgb( $color );
- }
- // ====================
- // = Public Interface =
- // ====================
- /**
- * Given a HEX string returns a HSL array equivalent.
- * @param string $color
- * @return array HSL associative array
- */
- public static function hexToHsl( $color ) {
- // Sanity check
- $color = self::_checkHex( $color );
- // Convert HEX to DEC
- $R = hexdec( $color[0] . $color[1] );
- $G = hexdec( $color[2] . $color[3] );
- $B = hexdec( $color[4] . $color[5] );
- $HSL = array();
- $var_R = ( $R / 255 );
- $var_G = ( $G / 255 );
- $var_B = ( $B / 255 );
- $var_Min = min( $var_R, $var_G, $var_B );
- $var_Max = max( $var_R, $var_G, $var_B );
- $del_Max = $var_Max - $var_Min;
- $L = ( $var_Max + $var_Min ) / 2;
- if ( $del_Max == 0 ) {
- $H = 0;
- $S = 0;
- } else {
- if ( $L < 0.5 ) {
- $S = $del_Max / ( $var_Max + $var_Min );
- } else {
- $S = $del_Max / ( 2 - $var_Max - $var_Min );
- }
- $del_R = ( ( ( $var_Max - $var_R ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
- $del_G = ( ( ( $var_Max - $var_G ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
- $del_B = ( ( ( $var_Max - $var_B ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
- if ( $var_R == $var_Max ) {
- $H = $del_B - $del_G;
- } elseif ( $var_G == $var_Max ) {
- $H = ( 1 / 3 ) + $del_R - $del_B;
- } elseif ( $var_B == $var_Max ) {
- $H = ( 2 / 3 ) + $del_G - $del_R;
- }
- if ( $H < 0 ) {
- $H++;
- }
- if ( $H > 1 ) {
- $H--;
- }
- }
- $HSL['H'] = ( $H * 360 );
- $HSL['S'] = $S;
- $HSL['L'] = $L;
- return $HSL;
- }
- /**
- * Given a HSL associative array returns the equivalent HEX string
- * @param array $hsl
- * @return string HEX string
- * @throws Exception "Bad HSL Array"
- */
- public static function hslToHex( $hsl = array() ) {
- // Make sure it's HSL
- if ( empty( $hsl ) || ! isset( $hsl['H'] ) || ! isset( $hsl['S'] ) || ! isset( $hsl['L'] ) ) {
- throw new Exception( esc_html__( 'Parameter was not an HSL array', 'pen' ) );
- }
- list($H,$S,$L) = array( $hsl['H'] / 360, $hsl['S'], $hsl['L'] );
- if ( $S == 0 ) {
- $r = $L * 255;
- $g = $L * 255;
- $b = $L * 255;
- } else {
- if ( $L < 0.5 ) {
- $var_2 = $L * ( 1 + $S );
- } else {
- $var_2 = ( $L + $S ) - ( $S * $L );
- }
- $var_1 = 2 * $L - $var_2;
- $r = round( 255 * self::_huetorgb( $var_1, $var_2, $H + ( 1 / 3 ) ) );
- $g = round( 255 * self::_huetorgb( $var_1, $var_2, $H ) );
- $b = round( 255 * self::_huetorgb( $var_1, $var_2, $H - ( 1 / 3 ) ) );
- }
- // Convert to hex
- $r = dechex( $r );
- $g = dechex( $g );
- $b = dechex( $b );
- // Make sure we get 2 digits for decimals
- $r = ( strlen( '' . $r ) === 1 ) ? '0' . $r : $r;
- $g = ( strlen( '' . $g ) === 1 ) ? '0' . $g : $g;
- $b = ( strlen( '' . $b ) === 1 ) ? '0' . $b : $b;
- return $r . $g . $b;
- }
- /**
- * Given a HEX string returns a RGB array equivalent.
- * @param string $color
- * @return array RGB associative array
- */
- public static function hexToRgb( $color ) {
- // Sanity check
- $color = self::_checkHex( $color );
- // Convert HEX to DEC
- $R = hexdec( $color[0] . $color[1] );
- $G = hexdec( $color[2] . $color[3] );
- $B = hexdec( $color[4] . $color[5] );
- $RGB['R'] = $R;
- $RGB['G'] = $G;
- $RGB['B'] = $B;
- return $RGB;
- }
- /**
- * Given an RGB associative array returns the equivalent HEX string
- * @param array $rgb
- * @return string RGB string
- * @throws Exception "Bad RGB Array"
- */
- public static function rgbToHex( $rgb = array() ) {
- // Make sure it's RGB
- if ( empty( $rgb ) || ! isset( $rgb['R'] ) || ! isset( $rgb['G'] ) || ! isset( $rgb['B'] ) ) {
- throw new Exception( esc_html__( 'Parameter was not an RGB array', 'pen' ) );
- }
- // https://github.com/mexitek/phpColors/issues/25#issuecomment-88354815
- // Convert RGB to HEX
- $hex[0] = str_pad( dechex( $rgb['R'] ), 2, '0', STR_PAD_LEFT );
- $hex[1] = str_pad( dechex( $rgb['G'] ), 2, '0', STR_PAD_LEFT );
- $hex[2] = str_pad( dechex( $rgb['B'] ), 2, '0', STR_PAD_LEFT );
- return implode( '', $hex );
- }
- /**
- * Given a HEX value, returns a darker color. If no desired amount provided, then the color halfway between
- * given HEX and black will be returned.
- * @param int $amount
- * @return string Darker HEX value
- */
- public function darken( $amount = self::DEFAULT_ADJUST ) {
- // Darken
- $darkerHSL = $this->_darken( $this->_hsl, $amount );
- // Return as HEX
- return self::hslToHex( $darkerHSL );
- }
- /**
- * Given a HEX value, returns a lighter color. If no desired amount provided, then the color halfway between
- * given HEX and white will be returned.
- * @param int $amount
- * @return string Lighter HEX value
- */
- public function lighten( $amount = self::DEFAULT_ADJUST ) {
- // Lighten
- $lighterHSL = $this->_lighten( $this->_hsl, $amount );
- // Return as HEX
- return self::hslToHex( $lighterHSL );
- }
- /**
- * Given a HEX value, returns a mixed color. If no desired amount provided, then the color mixed by this ratio
- * @param string $hex2 Secondary HEX value to mix with
- * @param int $amount = -100..0..+100
- * @return string mixed HEX value
- */
- public function mix( $hex2, $amount = 0 ) {
- $rgb2 = self::hexToRgb( $hex2 );
- $mixed = $this->_mix( $this->_rgb, $rgb2, $amount );
- // Return as HEX
- return self::rgbToHex( $mixed );
- }
- /**
- * Creates an array with two shades that can be used to make a gradient
- * @param int $amount Optional percentage amount you want your contrast color
- * @return array An array with a 'light' and 'dark' index
- */
- public function makeGradient( $amount = self::DEFAULT_ADJUST ) {
- // Decide which color needs to be made
- if ( $this->isLight() ) {
- $lightColor = $this->_hex;
- $darkColor = $this->darken( $amount );
- } else {
- $lightColor = $this->lighten( $amount );
- $darkColor = $this->_hex;
- }
- // Return our gradient array
- return array(
- 'light' => $lightColor,
- 'dark' => $darkColor,
- );
- }
- /**
- * Returns whether or not given color is considered "light"
- * @param string|Boolean $color
- * @param int $lighterThan
- * @return boolean
- */
- public function isLight( $color = false, $lighterThan = 130 ) {
- // Get our color
- $color = ( $color ) ? $color : $this->_hex;
- // Calculate straight from rbg
- $r = hexdec( $color[0] . $color[1] );
- $g = hexdec( $color[2] . $color[3] );
- $b = hexdec( $color[4] . $color[5] );
- return ( ( $r * 299 + $g * 587 + $b * 114 ) / 1000 > $lighterThan );
- }
- /**
- * Returns whether or not a given color is considered "dark"
- * @param string|Boolean $color
- * @param int $darkerThan
- * @return boolean
- */
- public function isDark( $color = false, $darkerThan = 130 ) {
- // Get our color
- $color = ( $color ) ? $color : $this->_hex;
- // Calculate straight from rbg
- $r = hexdec( $color[0] . $color[1] );
- $g = hexdec( $color[2] . $color[3] );
- $b = hexdec( $color[4] . $color[5] );
- return ( ( $r * 299 + $g * 587 + $b * 114 ) / 1000 <= $darkerThan );
- }
- /**
- * Returns the complimentary color
- * @return string Complementary hex color
- *
- */
- public function complementary() {
- // Get our HSL
- $hsl = $this->_hsl;
- // Adjust Hue 180 degrees
- $hsl['H'] += ( $hsl['H'] > 180 ) ? -180 : 180;
- // Return the new value in HEX
- return self::hslToHex( $hsl );
- }
- /**
- * Returns your color's HSL array
- */
- public function getHsl() {
- return $this->_hsl;
- }
- /**
- * Returns your original color
- */
- public function getHex() {
- return $this->_hex;
- }
- /**
- * Returns your color's RGB array
- */
- public function getRgb() {
- return $this->_rgb;
- }
- /**
- * Returns the cross browser CSS3 gradient
- * @param int $amount Optional: percentage amount to light/darken the gradient
- * @param boolean $vintageBrowsers Optional: include vendor prefixes for browsers that almost died out already
- * @param string $prefix Optional: prefix for every lines
- * @param string $suffix Optional: suffix for every lines
- * @link http://caniuse.com/css-gradients Resource for the browser support
- * @return string CSS3 gradient for chrome, safari, firefox, opera and IE10
- */
- public function getCssGradient( $amount = self::DEFAULT_ADJUST, $vintageBrowsers = false, $suffix = '', $prefix = '' ) {
- // Get the recommended gradient
- $g = $this->makeGradient( $amount );
- $css = '';
- /* fallback/image non-cover color */
- $css .= "{$prefix}background-color: #" . $this->_hex . ";{$suffix}";
- /* IE Browsers */
- $css .= "{$prefix}filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#" . $g['light'] . "', endColorstr='#" . $g['dark'] . "');{$suffix}";
- /* Safari 4+, Chrome 1-9 */
- if ( $vintageBrowsers ) {
- $css .= "{$prefix}background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#" . $g['light'] . '), to(#' . $g['dark'] . "));{$suffix}";
- }
- /* Safari 5.1+, Mobile Safari, Chrome 10+ */
- $css .= "{$prefix}background-image: -webkit-linear-gradient(top, #" . $g['light'] . ', #' . $g['dark'] . ");{$suffix}";
- /* Firefox 3.6+ */
- if ( $vintageBrowsers ) {
- $css .= "{$prefix}background-image: -moz-linear-gradient(top, #" . $g['light'] . ', #' . $g['dark'] . ");{$suffix}";
- }
- /* Opera 11.10+ */
- if ( $vintageBrowsers ) {
- $css .= "{$prefix}background-image: -o-linear-gradient(top, #" . $g['light'] . ', #' . $g['dark'] . ");{$suffix}";
- }
- /* Unprefixed version (standards): FF 16+, IE10+, Chrome 26+, Safari 7+, Opera 12.1+ */
- $css .= "{$prefix}background-image: linear-gradient(to bottom, #" . $g['light'] . ', #' . $g['dark'] . ");{$suffix}";
- // Return our CSS
- return $css;
- }
- // ===========================
- // = Private Functions Below =
- // ===========================
- /**
- * Darkens a given HSL array
- * @param array $hsl
- * @param int $amount
- * @return array $hsl
- */
- private function _darken( $hsl, $amount = self::DEFAULT_ADJUST ) {
- // Check if we were provided a number
- if ( $amount ) {
- $hsl['L'] = ( $hsl['L'] * 100 ) - $amount;
- $hsl['L'] = ( $hsl['L'] < 0 ) ? 0 : $hsl['L'] / 100;
- } else {
- // We need to find out how much to darken
- $hsl['L'] = $hsl['L'] / 2;
- }
- return $hsl;
- }
- /**
- * Lightens a given HSL array
- * @param array $hsl
- * @param int $amount
- * @return array $hsl
- */
- private function _lighten( $hsl, $amount = self::DEFAULT_ADJUST ) {
- // Check if we were provided a number
- if ( $amount ) {
- $hsl['L'] = ( $hsl['L'] * 100 ) + $amount;
- $hsl['L'] = ( $hsl['L'] > 100 ) ? 1 : $hsl['L'] / 100;
- } else {
- // We need to find out how much to lighten
- $hsl['L'] += ( 1 - $hsl['L'] ) / 2;
- }
- return $hsl;
- }
- /**
- * Mix 2 rgb colors and return an rgb color
- * @param array $rgb1
- * @param array $rgb2
- * @param int $amount ranged -100..0..+100
- * @return array $rgb
- *
- * ported from http://phpxref.pagelines.com/nav.html?includes/class.colors.php.source.html
- */
- private function _mix( $rgb1, $rgb2, $amount = 0 ) {
- $r1 = ( $amount + 100 ) / 100;
- $r2 = 2 - $r1;
- $rmix = ( ( $rgb1['R'] * $r1 ) + ( $rgb2['R'] * $r2 ) ) / 2;
- $gmix = ( ( $rgb1['G'] * $r1 ) + ( $rgb2['G'] * $r2 ) ) / 2;
- $bmix = ( ( $rgb1['B'] * $r1 ) + ( $rgb2['B'] * $r2 ) ) / 2;
- return array(
- 'R' => $rmix,
- 'G' => $gmix,
- 'B' => $bmix,
- );
- }
- /**
- * Given a Hue, returns corresponding RGB value
- * @param int $v1
- * @param int $v2
- * @param int $vH
- * @return int
- */
- private static function _huetorgb( $v1, $v2, $vH ) {
- if ( $vH < 0 ) {
- $vH += 1;
- }
- if ( $vH > 1 ) {
- $vH -= 1;
- }
- if ( ( 6 * $vH ) < 1 ) {
- return ( $v1 + ( $v2 - $v1 ) * 6 * $vH );
- }
- if ( ( 2 * $vH ) < 1 ) {
- return $v2;
- }
- if ( ( 3 * $vH ) < 2 ) {
- return ( $v1 + ( $v2 - $v1 ) * ( ( 2 / 3 ) - $vH ) * 6 );
- }
- return $v1;
- }
- /**
- * You need to check if you were given a good hex string
- * @param string $hex
- * @return string Color
- * @throws Exception "Bad color format"
- */
- private static function _checkHex( $hex ) {
- // Strip # sign is present
- $color = str_replace( '#', '', $hex );
- // Make sure it's 6 digits
- if ( strlen( $color ) == 3 ) {
- $color = $color[0] . $color[0] . $color[1] . $color[1] . $color[2] . $color[2];
- } elseif ( strlen( $color ) != 6 ) {
- throw new Exception( esc_html__( 'HEX color needs to be 6 or 3 digits long', 'pen' ) );
- }
- return $color;
- }
- /**
- * Converts object into its string representation
- * @return string Color
- */
- public function __toString() {
- return '#' . $this->getHex();
- }
- }
|