<?php
class Color {
/*! properties */
public $hex = '#000';
public $rgb = 'rgb( 0, 0, 0 )';
public $hsl = 'hsl( 0, 0%, 0% )';
private $_rgb = array(0,0,0);
private $_hsl = array(0,0,0);
<?php
class Color {
/*! properties */
public $hex = '#000';
public $rgb = 'rgb( 0, 0, 0 )';
public $hsl = 'hsl( 0, 0%, 0% )';
private $_rgb = array(0,0,0);
private $_hsl = array(0,0,0);
uncomment when implementing alpha support
/*
private $alpha = 1;
private $ahex = '#ff000000';
private $rgba = 'rgba( 0, 0, 0, 1 )';
private $hsla = 'hsla( 0, 0, 0, 1 )';
*/
/*! init */
public function __construct($input = '#000') {
if (is_string($input)) {
if (strpos($input, '#') === 0) {
$this->hex = $input;
$this->update('hex');
} else if (strpos($input, 'rgb') === 0) {
$this->rgb = $input;
$this->update('rgb');
} else if (strpos($input, 'hsl') === 0) {
$this->hsl = $input;
$this->update('hsl');
} else { error_log('Color Object sez: I need a valid hex, rgb, or hsl color string.'); }
}
return $this;
}
public function __clone() {
return new Color ($this->hex);
}
/*! color methods returning new colors */
public function mix($color2, $weight = 50) {
if (is_string($color2)) {
if (strpos($color2, '#') === 0) {
$color2 = hex2rgb($color2);
} else if (strpos($color2, 'rgb') === 0) {
$color2 = explode(',',str_replace(array('rgb(',')',' '),'',$color2));
} else if (strpos($color2, 'hsl') === 0) {
$color2 = hsl2rgb(explode(',',str_replace(array('hsl(',')',' ','%'),'',$color2)));
} else {
error_log(
'Mix Method sez: I need a valid hex, rgb, or hsl ' .
'string or a Color object in order to mix.');
return false;
}
} else if (is_object($color2) && get_class($color2) === 'Color') {
$color2 = explode(',',str_replace(array('rgb(',')',' '),'',$color2->rgb));
} else {
error_log(
'Mix Method sez: I need a valid hex, rgb, or hsl ' .
'string or a Color object in order to mix.');
return false;
}
validate $weight
$weight = $weight * 1;
if (! is_numeric($weight)) {
error_log(
'Mix Method sez: If you pass me a `$weight`, it\'s ' .
'gotta be a number or percentage string.');
return false;
}
convert $weight
from percentage to decimal
$w1 = ($weight * 1) / 100;
uncomment when implementing alpha support
/*
factor in the alpha channels
$w = $w1 * 2 - 1;
$a = $this->alpha - $colorObject2->alpha;
$w = ($w * $a === -1) ? $w : ($w + $a) / (1 + $w * $a);
set new $w1
, weighted with alpha channels
$w1 = ($w + 1) / 2;
*/
$w2 = 1 - $w1;
$mixr = $this->_rgb[0] * $w1 + $color2[0] * $w2;
$mixg = $this->_rgb[1] * $w1 + $color2[1] * $w2;
$mixb = $this->_rgb[2] * $w1 + $color2[2] * $w2;
uncomment when implementing alpha support
/*
$mixa = $this->_rgb[3] * $w1 + $color2[3] * $w2;
if ($mixa < 1) {
return rgba() if alpha isn't 1
return $this->rgb(array($mixr,$mixg,$mixb,$mixa));
} else {
otherwise, return hex
return $this->rgb2hex(array($mixr,$mixg,$mixb));
}
*/
return hex string
return $this->rgb2hex(array($mixr,$mixg,$mixb));
}
/*! color methods returning this color */
public function spin($degrees) {
check if $degrees
is valid
if (is_string($degrees)) { floatval(ereg_replace("[^-0-9\.]","",$degrees)); }
modulus (%
) keeps the hue between -360 and 360
$h = ($this->_hsl[0] + $degrees) % 360;
$s = $this->_hsl[1];
$l = $this->_hsl[2];
$this->_hsl = array($h,$s,$l);
$this->update('_hsl');
allows chainability
return $this;
}
public function lighten($percent) {
check if $percent
is valid
if (is_string($percent)) { floatval(ereg_replace("[^-0-9\.]","",$percent)); }
$h = $this->_hsl[0];
$s = $this->_hsl[1];
ensure $l
is no lower than 0% and no higher than 100%
$l = min(1, max(0, $this->_hsl[2] + $percent / 100));
$this->_hsl = array($h,$s,$l);
$this->update('_hsl');
return $this;
}
public function darken($percent) {
if (is_string($percent)) { floatval(ereg_replace("[^-0-9\.]","",$percent)); }
$h = $this->_hsl[0];
$s = $this->_hsl[1];
$l = min(1, max(0, $this->_hsl[2] - $percent / 100));
$this->_hsl = array($h,$s,$l);
$this->update('_hsl');
return $this;
}
public function saturate($percent) {
if (is_string($percent)) { floatval(ereg_replace("[^-0-9\.]","",$percent)); }
$h = $this->_hsl[0];
$s = min(1, max(0, $this->_hsl[1] + $percent / 100));
$l = $this->_hsl[2];
$this->_hsl = array($h,$s,$l);
$this->update('_hsl');
return $this;
}
public function desaturate($percent) {
if (is_string($percent)) { floatval(ereg_replace("[^-0-9\.]","",$percent)); }
$h = $this->_hsl[0];
$s = min(1, max(0, $this->_hsl[1] - $percent / 100));
$l = $this->_hsl[2];
$this->_hsl = array($h,$s,$l);
$this->update('_hsl');
return $this;
}
/*! color format converters */
private function hex2rgb($strhex) {
$strhex = str_replace('#', '', $strhex);
if (strlen($strhex) == 3) {
$r = hexdec(substr($strhex,0,1) . substr($strhex,0,1));
$g = hexdec(substr($strhex,1,1) . substr($strhex,1,1));
$b = hexdec(substr($strhex,2,1) . substr($strhex,2,1));
} else {
$r = hexdec(substr($strhex,0,2));
$g = hexdec(substr($strhex,2,2));
$b = hexdec(substr($strhex,4,2));
}
return array($r,$g,$b);
}
private function rgb2hex($rgbarr) {
$hexstr = '#';
foreach ($rgbarr as $v) {
$v = dechex($v);
if (strlen($v) < 2) { $v = '0' . $v; } // zero fill
if (strlen($v) < 2) { $v = '0' . $v; } // double check
$hexstr .= $v;
} unset($v);
return $hexstr;
}
private function rgb2hsl($rgbarr) {
$r = $rgbarr[0] / 255;
$g = $rgbarr[1] / 255;
$b = $rgbarr[2] / 255;
$max = max($r,$g,$b);
$min = min($r,$g,$b);
$h = 0;
$s = 0;
$l = ($max + $min) / 2;
$d = $max - $min;
if ($d !== 0) {
if ($l > .5) {
$s = $d / (2 - $max - $min);
} else {
$s = $d / ($max + $min);
}
switch ($max) {
case $r:
$h = 60 * (($g - $b) / $d + ($g < $b ? 6 : 0));
break;
case $g:
$h = 60 * (($b - $r) / $d + 2);
break;
case $b:
$h = 60 * (($r - $g) / $d + 4);
break;
}
}
$h = round($h);
return array($h,$s,$l);
}
private function hsl2rgb($hslarr) {
$h = abs($hslarr[0]);
$s = $hslarr[1];
$l = $hslarr[2];
$c = ( 1 - abs( 2 * $l - 1 ) ) * $s;
$x = $c * ( 1 - abs( fmod( ( $h / 60 ), 2 ) - 1 ) );
$m = $l - ( $c / 2 );
if ($h < 60) {
$r = round(($c + $m) * 255);
$g = round(($x + $m) * 255);
$b = round((0 + $m) * 255);
} else if ($h < 120) {
$r = round(($x + $m) * 255);
$g = round(($c + $m) * 255);
$b = round((0 + $m) * 255);
} else if ($h < 180) {
$r = round((0 + $m) * 255);
$g = round(($c + $m) * 255);
$b = round(($x + $m) * 255);
} else if ($h < 240) {
$r = round((0 + $m) * 255);
$g = round(($x + $m) * 255);
$b = round(($c + $m) * 255);
} else if ($h < 300) {
$r = round(($x + $m) * 255);
$g = round((0 + $m) * 255);
$b = round(($c + $m) * 255);
} else {
$r = round(($c + $m) * 255);
$g = round((0 + $m) * 255);
$b = round(($x + $m) * 255);
}
return array($r,$g,$b);
}
/*! array & string converters */
private function rgb($rgbarr) { return 'rgb( ' . implode(', ', $rgbarr) . ' )'; }
private function hsl($hslarr) {
$hslarr[1] *= 100; $hslarr[1] .= '%';
$hslarr[2] *= 100; $hslarr[2] .= '%';
return 'hsl( ' . implode(', ', $hslarr) . ' )';
}
private function rgbExplode($rgbstr) {
$_rgb = explode(',',str_replace(array('rgb(',')',' '),'',$rgbstr));
$_rgb[0] /= 1;
$_rgb[1] /= 1;
$_rgb[2] /= 1;
return $_rgb;
}
private function hslExplode($hslstr) {
$_hsl = explode(',',str_replace(array('hsl(',')',' ','%'),'',$hslstr));
$_hsl[1] /= 100;
$_hsl[2] /= 100;
return $_hsl;
}
/*! update */
private function update($fromThis = '_hsl') { // default, 'cause methods use hsl
switch ($fromThis) {
case 'hex':
$this->_rgb = $this->hex2rgb($this->hex);
$this->rgb = $this->rgb($this->_rgb);
$this->_hsl = $this->rgb2hsl($this->_rgb);
$this->hsl = $this->hsl($this->_hsl);
break;
case 'rgb':
$this->_rgb = $this->rgbExplode($this->rgb);
$this->_hsl = $this->rgb2hsl($this->_rgb);
$this->hsl = $this->hsl($this->_hsl);
$this->hex = $this->rgb2hex($this->_rgb);
break;
case 'hsl':
$this->_hsl = $this->hslExplode($this->hsl);
$this->_rgb = $this->hsl2rgb($this->_hsl);
$this->rgb = $this->rgb($this->_rgb);
$this->hex = $this->rgb2hex($this->_rgb);
break;
case '_rgb':
case 'rgbarr':
$this->rgb = $this->rgb($this->_rgb);
$this->_hsl = $this->rgb2hsl($this->_rgb);
$this->hsl = $this->hsl($this->_hsl);
$this->hex = $this->rgb2hex($this->_rgb);
break;
case '_hsl':
case 'hslarr':
$this->hsl = $this->hsl($this->_hsl);
$this->_rgb = $this->hsl2rgb($this->_hsl);
$this->rgb = $this->rgb($this->_rgb);
$this->hex = $this->rgb2hex($this->_rgb);
break;
throws an error if $fromThis
doesn't match any of the above cases
default:
error_log('Update sez: Bad argument ("' . $fromThis . '").');
break;
}
}
}
?>