Related
Does anyone know a PHP function (for >5.3) which can convert an HSL color to either RGB or Hex? I've tried a dozen Google searches and none of the functions I have found work as expected.
It doesn't matter whether the function converts to RGB or hex because converting between those two is trivial. The inputs are HSL values for CSS (Hue: 0–360, Saturation: 0–100, Lightness: 0–100).
Edit: Specifying the input and output format would be a bonus :)
Taking the code from one of the answers in the link of Jim's comment (PHP HSV to RGB formula comprehension), we can compute it as follows:
<?php
$hue = 209;
$sat = 75;
$lum = 60;
$hue /= 360;
$sat /= 100;
$lum /= 100;
$result = ColorHSLToRGB($hue, $sat, $lum);
var_dump($result); echo '<br>';
printf("rgb = %d,%d,%d<br>", $result['r'], $result['g'], $result['b']);
function ColorHSLToRGB($h, $s, $l){
$r = $l;
$g = $l;
$b = $l;
$v = ($l <= 0.5) ? ($l * (1.0 + $s)) : ($l + $s - $l * $s);
if ($v > 0){
$m;
$sv;
$sextant;
$fract;
$vsf;
$mid1;
$mid2;
$m = $l + $l - $v;
$sv = ($v - $m ) / $v;
$h *= 6.0;
$sextant = floor($h);
$fract = $h - $sextant;
$vsf = $v * $sv * $fract;
$mid1 = $m + $vsf;
$mid2 = $v - $vsf;
switch ($sextant)
{
case 0:
$r = $v;
$g = $mid1;
$b = $m;
break;
case 1:
$r = $mid2;
$g = $v;
$b = $m;
break;
case 2:
$r = $m;
$g = $v;
$b = $mid1;
break;
case 3:
$r = $m;
$g = $mid2;
$b = $v;
break;
case 4:
$r = $mid1;
$g = $m;
$b = $v;
break;
case 5:
$r = $v;
$g = $m;
$b = $mid2;
break;
}
}
return array('r' => $r * 255.0, 'g' => $g * 255.0, 'b' => $b * 255.0);
}
?>
Output:
array(3) { ["r"]=> float(76.5) ["g"]=> float(155.55) ["b"]=> float(229.5) }
rgb = 76,155,229
Putting this together (which helped me produce this chart)
/**
* convert a HSL colorscheme to either Hexadecimal (default) or RGB.
*
* We want a method where we can programmatically generate a series of colors
* between two values (eg. red to green) which is easy to do with HSL because
* you just change the hue. (0 = red, 120 = green). You can use this function
* to convert those hsl color values to either the rgb or hexadecimal color scheme.
* e.g. You have
* hsl(50, 100%, 50%)
* To convert,
* $hex = convertHSL(50,100,50); // returns #ffd500
* or
* $rgb = convertHSL(50,100,50, false); // returns rgb(255, 213, 0)
*
* see https://coderwall.com/p/dvsxwg/smoothly-transition-from-green-to-red
* #param int $h the hue
* #param int $s the saturation
* #param int $l the luminance
* #param bool $toHex whether you want hexadecimal equivalent or rgb equivalent
* #return string usable in HTML or CSS
*/
function convertHSL($h, $s, $l, $toHex=true){
$h /= 360;
$s /=100;
$l /=100;
$r = $l;
$g = $l;
$b = $l;
$v = ($l <= 0.5) ? ($l * (1.0 + $s)) : ($l + $s - $l * $s);
if ($v > 0){
$m;
$sv;
$sextant;
$fract;
$vsf;
$mid1;
$mid2;
$m = $l + $l - $v;
$sv = ($v - $m ) / $v;
$h *= 6.0;
$sextant = floor($h);
$fract = $h - $sextant;
$vsf = $v * $sv * $fract;
$mid1 = $m + $vsf;
$mid2 = $v - $vsf;
switch ($sextant)
{
case 0:
$r = $v;
$g = $mid1;
$b = $m;
break;
case 1:
$r = $mid2;
$g = $v;
$b = $m;
break;
case 2:
$r = $m;
$g = $v;
$b = $mid1;
break;
case 3:
$r = $m;
$g = $mid2;
$b = $v;
break;
case 4:
$r = $mid1;
$g = $m;
$b = $v;
break;
case 5:
$r = $v;
$g = $m;
$b = $mid2;
break;
}
}
$r = round($r * 255, 0);
$g = round($g * 255, 0);
$b = round($b * 255, 0);
if ($toHex) {
$r = ($r < 15)? '0' . dechex($r) : dechex($r);
$g = ($g < 15)? '0' . dechex($g) : dechex($g);
$b = ($b < 15)? '0' . dechex($b) : dechex($b);
return "#$r$g$b";
} else {
return "rgb($r, $g, $b)";
}
My tests of all other implementations showed only weird and possibly unplausible results. Here is a PHP implementation of #Mohsen's code from https://stackoverflow.com/a/9493060/1598477. Plus a test to show the full beauty...
Sorry to cross-post this. But I really haven't seen any other implementation that gives the quality I needed.
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* #param {number} h The hue
* #param {number} s The saturation
* #param {number} l The lightness
* #return {Array} The RGB representation
*/
function hue2rgb($p, $q, $t){
if($t < 0) $t += 1;
if($t > 1) $t -= 1;
if($t < 1/6) return $p + ($q - $p) * 6 * $t;
if($t < 1/2) return $q;
if($t < 2/3) return $p + ($q - $p) * (2/3 - $t) * 6;
return $p;
}
function hslToRgb($h, $s, $l){
if($s == 0){
$r = $l;
$g = $l;
$b = $l; // achromatic
}else{
$q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s;
$p = 2 * $l - $q;
$r = hue2rgb($p, $q, $h + 1/3);
$g = hue2rgb($p, $q, $h);
$b = hue2rgb($p, $q, $h - 1/3);
}
return array(round($r * 255), round($g * 255), round($b * 255));
}
/* Uncomment to test * /
for ($i=0;$i<360;$i++) {
$rgb=hslToRgb($i/360, 1, .9);
echo '<div style="background-color:rgb(' .$rgb[0] . ', ' . $rgb[1] . ', ' . $rgb[2] . ');padding:2px;"></div>';
}
/* End Test */
The PEAR package Image_Color2 has methods to transform between color models - see convertTo.
Here is my solution
HSV value restrictions: $H [0-359], $S [0-100], $V [0-100]
function hsv_to_rgb($iH, $iS, $iV) {
if($iH < 0) $iH = 0;
if($iH > 360) $iH = 360;
if($iS < 0) $iS = 0;
if($iS > 100) $iS = 100;
if($iV < 0) $iV = 0;
if($iV > 100) $iV = 100;
$dS = $iS/100.0;
$dV = $iV/100.0;
$dC = $dV*$dS;
$dH = $iH/60.0;
$dT = $dH;
while($dT >= 2.0) $dT -= 2.0; // php modulus does not work with float
$dX = $dC*(1-abs($dT-1)); // as used in the Wikipedia link
switch($dH) {
case($dH >= 0.0 && $dH < 1.0):
$dR = $dC; $dG = $dX; $dB = 0.0; break;
case($dH >= 1.0 && $dH < 2.0):
$dR = $dX; $dG = $dC; $dB = 0.0; break;
case($dH >= 2.0 && $dH < 3.0):
$dR = 0.0; $dG = $dC; $dB = $dX; break;
case($dH >= 3.0 && $dH < 4.0):
$dR = 0.0; $dG = $dX; $dB = $dC; break;
case($dH >= 4.0 && $dH < 5.0):
$dR = $dX; $dG = 0.0; $dB = $dC; break;
case($dH >= 5.0 && $dH < 6.0):
$dR = $dC; $dG = 0.0; $dB = $dX; break;
default:
$dR = 0.0; $dG = 0.0; $dB = 0.0; break;
}
$dM = $dV - $dC;
$dR += $dM; $dG += $dM; $dB += $dM;
$dR *= 255; $dG *= 255; $dB *= 255;
return array(round($dR), round($dG), round($dB));
}
Copied from this SO Answer by Cullub.
This code worked perfectly to convert a user email to user avatar colour. After long hours of searching, I got the correct hex value similar to the one generated using javascript on the front end.
TL;DR: The full code can be found here on Pastebin.
/**
* convert user email to hsl for user avatar
* #param string $string
* #return string HEX color code
*/
function stringToColor($string)
{
$hash = 0;
$l = 70;
$s = 60;
for ($i = 0; $i < strlen($string); $i++) {
$hash = ord($string[$i]) + (($hash << 5) - $hash);
}
$h = fmod($hash, 360);
return $this->hslToHex($h, $s, $l, true);
}
/**
* Converts HSL to Hex by converting it to
* RGB, then converting that to hex.
*
* string hslToHex($h, $s, $l[, $prependPound = true]
*
* $h is the Degrees value of the Hue
* $s is the Percentage value of the Saturation
* $l is the Percentage value of the Lightness
* $prependPound is a bool, whether you want a pound
* sign prepended. (optional - default=true)
*
* Calls:
* hslToRgb
*
* Output: Hex in the format: #00ff88 (with
* pound sign). Rounded to the nearest whole
* number.
*/
function hslToHex($h, $s, $l, $prependPound = true)
{
//convert hsl to rgb
$rgb = $this->hslToRgb($h, $s, $l);
//convert rgb to hex
$hexR = $rgb['r'];
$hexG = $rgb['g'];
$hexB = $rgb['b'];
//round to the nearest whole number
$hexR = round($hexR);
$hexG = round($hexG);
$hexB = round($hexB);
//convert to hex
$hexR = dechex($hexR);
$hexG = dechex($hexG);
$hexB = dechex($hexB);
//check for a non-two string length
//if it's 1, we can just prepend a
//0, but if it is anything else non-2,
//it must return false, as we don't
//know what format it is in.
if (strlen($hexR) != 2) {
if (strlen($hexR) == 1) {
//probably in format #0f4, etc.
$hexR = "0" . $hexR;
} else {
//unknown format
return false;
}
}
if (strlen($hexG) != 2) {
if (strlen($hexG) == 1) {
$hexG = "0" . $hexG;
} else {
return false;
}
}
if (strlen($hexB) != 2) {
if (strlen($hexB) == 1) {
$hexB = "0" . $hexB;
} else {
return false;
}
}
//if prependPound is set, will prepend a
//# sign to the beginning of the hex code.
//(default = true)
$hex = "";
if ($prependPound) {
$hex = "#";
}
$hex = $hex . $hexR . $hexG . $hexB;
return $hex;
}
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/.
* Assumes h, s, and l are in the format Degrees,
* Percent, Percent, and returns r, g, and b in
* the range [0 - 255].
*
* Called by hslToHex by default.
*
* Calls:
* degPercPercToHsl
* hueToRgb
*
* #param Number h The hue value
* #param Number s The saturation level
* #param Number l The luminence
* #return Array The RGB representation
*/
function hslToRgb($h, $s, $l)
{
//convert the hue's 360 degrees in a circle to 1
$h /= 360;
//convert the saturation and lightness to the 0-1
//range by multiplying by 100
$s /= 100;
$l /= 100;
//If there's no saturation, the color is a greyscale,
//so all three RGB values can be set to the lightness.
//(Hue doesn't matter, because it's grey, not color)
if ($s == 0) {
$r = $l * 255;
$g = $l * 255;
$b = $l * 255;
} else {
//calculate some temperary variables to make the
//calculation eaisier.
if ($l < 0.5) {
$temp2 = $l * (1 + $s);
} else {
$temp2 = ($l + $s) - ($s * $l);
}
$temp1 = 2 * $l - $temp2;
//run the calculated vars through hueToRgb to
//calculate the RGB value. Note that for the Red
//value, we add a third (120 degrees), to adjust
//the hue to the correct section of the circle for
//red. Simalarly, for blue, we subtract 1/3.
$r = 255 * $this->hueToRgb($temp1, $temp2, $h + (1 / 3));
$g = 255 * $this->hueToRgb($temp1, $temp2, $h);
$b = 255 * $this->hueToRgb($temp1, $temp2, $h - (1 / 3));
}
$rgb['r'] = $r;
$rgb['g'] = $g;
$rgb['b'] = $b;
return $rgb;
// return "rgb($r, $g, $b)";
}
/**
* Converts an HSL hue to it's RGB value.
*
* Input: $temp1 and $temp2 - temperary vars based on
* whether the lumanence is less than 0.5, and
* calculated using the saturation and luminence
* values.
* $hue - the hue (to be converted to an RGB
* value) For red, add 1/3 to the hue, green
* leave it alone, and blue you subtract 1/3
* from the hue.
*
* Output: One RGB value.
*
* Thanks to Easy RGB for this function (Hue_2_RGB).
* http://www.easyrgb.com/index.php?X=MATH&$h=19#text19
*
*/
function hueToRgb($temp1, $temp2, $hue)
{
if ($hue < 0) {
$hue += 1;
}
if ($hue > 1) {
$hue -= 1;
}
if ((6 * $hue) < 1) {
return ($temp1 + ($temp2 - $temp1) * 6 * $hue);
} elseif ((2 * $hue) < 1) {
return $temp2;
} elseif ((3 * $hue) < 2) {
return ($temp1 + ($temp2 - $temp1) * ((2 / 3) - $hue) * 6);
}
return $temp1;
}
If you have decimal RGB values (enhzflep showed how to get them), you can easily get the #ab01cd hex web string:
$rgb['r'] = ($t = round($rgb['r'] * 255, 0)) < 15 ? '0'.dechex($t) : dechex($t);
$rgb['g'] = ($t = round($rgb['g'] * 255, 0)) < 15 ? '0'.dechex($t) : dechex($t);
$rgb['b'] = ($t = round($rgb['b'] * 255, 0)) < 15 ? '0'.dechex($t) : dechex($t);
$hexweb = "#".$rgb['r'].$rgb['g'].$rgb['b'];
I am working on a dynamic store project and I use a loop to print all color options for a product as color boxes, however I really need to add a "border" to these colors which are light. I tried something like the following but It is very limited, it is actually limited to white color only, it won't catch something like #ddd, #eea... etc
Here is my loop:
foreach($colors as $color) {
$color = trim($color);
if (!empty($color)) {
if (in_array($color, array('white','White','#fff','#FFF','#FFFFFF','#ffffff'))) {
$bordercolor = '#bbb';
} else {
$bordercolor = $color;
}
}
}
Colors is an array from backend like: White, #000, #cc0000, etc. It is not practical to add all exceptions in the if/else condition too, any quick idea?
Transform HTML colour to RGB, then to Hue-Saturation-Lightnes (HSV)
<?php
function HTMLToRGB($htmlCode)
{
if($htmlCode[0] == '#')
$htmlCode = substr($htmlCode, 1);
if (strlen($htmlCode) == 3)
{
$htmlCode = $htmlCode[0] . $htmlCode[0] . $htmlCode[1] . $htmlCode[1] . $htmlCode[2] . $htmlCode[2];
}
$r = hexdec($htmlCode[0] . $htmlCode[1]);
$g = hexdec($htmlCode[2] . $htmlCode[3]);
$b = hexdec($htmlCode[4] . $htmlCode[5]);
return $b + ($g << 0x8) + ($r << 0x10);
}
function RGBToHSL($RGB) {
$r = 0xFF & ($RGB >> 0x10);
$g = 0xFF & ($RGB >> 0x8);
$b = 0xFF & $RGB;
$r = ((float)$r) / 255.0;
$g = ((float)$g) / 255.0;
$b = ((float)$b) / 255.0;
$maxC = max($r, $g, $b);
$minC = min($r, $g, $b);
$l = ($maxC + $minC) / 2.0;
if($maxC == $minC)
{
$s = 0;
$h = 0;
}
else
{
if($l < .5)
{
$s = ($maxC - $minC) / ($maxC + $minC);
}
else
{
$s = ($maxC - $minC) / (2.0 - $maxC - $minC);
}
if($r == $maxC)
$h = ($g - $b) / ($maxC - $minC);
if($g == $maxC)
$h = 2.0 + ($b - $r) / ($maxC - $minC);
if($b == $maxC)
$h = 4.0 + ($r - $g) / ($maxC - $minC);
$h = $h / 6.0;
}
$h = (int)round(255.0 * $h);
$s = (int)round(255.0 * $s);
$l = (int)round(255.0 * $l);
return (object) Array('hue' => $h, 'saturation' => $s, 'lightness' => $l);
}
$colour = '#F12346';
$rgb = HTMLToRGB($colour);
$hsl = RGBToHSL($rgb);
var_dump($hsl);
Usage:
$colour = '#F12346';
$rgb = HTMLToRGB($colour);
$hsl = RGBToHSL($rgb);
if($hsl->lightness > 200) {
// this is light colour!
}
Source:
http://www.caperna.org/computing/repository/hsl-rgb-color-conversion-php
Demo:
http://codepad.org/X7KV4n4n
What I'd do in this situation is detect the lightness of the color using HSL, and compare that against a certain percentage. For example, the lightness attribute in the HSL algorithm takes the chroma (M - m where M is the largest RGB value and m is the smallest RGB value) and divides that by 2.
function lightness($R = 255, $G = 255, $B = 255) {
return (max($R, $G, $B) + min($R, $G, $B)) / 510.0; // HSL algorithm
}
The above function would return a percentage of how light the color you've selected is (simple hex -> rgb conversions are required for this also, but that should be pretty easy). The reason I divided by 510 instead of 2 is because in order to get the percentage after dividing by 2, you divide by 255. To make it faster you can simply say: (x / 2) / 255 = x / 510. Then I'd compare the value returned by the above function to, say, 80%.
$r = hexdec($hex[0].$hex[1]);
$g = hexdec($hex[2].$hex[3]);
$b = hexdec($hex[4].$hex[5]);
if(lightness($r, $g, $b) >= .8) {
// add border
} else {
// no border
}
In addition to other formulas given by other answers, you may want to consider Luma.
function luma($r, $g, $b)
{
return (0.2126 * $r + 0.7152 * $g + 0.0722 * $b) / 255;
}
$l = luma(0, 15, 255);
Values closer to 0 will be darker. Values closer to 1 will be lighter.
Short way if you have RGB color as hexadecimal string:
$hexRGB = "4488BB";
if(hexdec(substr($hexRGB,0,2))+hexdec(substr($hexRGB,2,2))+hexdec(substr($hexRGB,4,2))> 381){
//bright color
}else{
//dark color
}
Note: The thereshold 381 is the sum of the values at average level. If you want the thereshold to be lighter or darker, upper or lower 381 in the range 1 - 765.
There also is a simpler way with even less code:
<?php
//Functions
function getRGB($colorCode) {
//Turn html color code into RGB
$var_R = substr($colorCode, 0, 2);
$var_G = substr($colorCode, 2, 2);
$var_B = substr($colorCode, 4, 2);
//Get Hex values
$val_R = hexdec($var_R);
$val_G = hexdec($var_G);
$val_B = hexdec($var_B);
//Red is seen as light too, gets fixed with this
$remRed = hexdec('99');
if ($val_R > $remRed) {
$RGB = $val_G.' '.$val_B;
} else {
$RGB = $val_R.' '.$val_G.' '.$val_B;
}
return $RGB;
}
function getHSL($R = 255, $G = 255, $B = 255) {
$hsl = (max($R, $G, $B) + min($R, $G, $B)) / 510.0;
return $hsl;
}
?>
Now the calling:
$color = 0000FF; //Blue
$RGBcode = getRGB($color); //Returns 0 0 255
$RGBcode = str_replace(' ', ', ', $RGBcode); //Replaces an empty space with a ,
$val_HSL = getHSL($RGBcode); //Returns value from 0.5 to 1
if ($val_HSL >= 0.8) {
//Reject color
} else {
//Accept Color
$color = '#'.$color; //Sets it to html: #0000FF
}
Here’s a short derived version from #Luca C.’s answer for colors in HEX format (e.g. #FFFFFF or #FFF)
<?php
function isDark($hex){
$average = 381; // range 1 - 765
if(strlen(trim($hex)) == 4){
$hex = "#" . substr($hex,1,1) . substr($hex,1,1) . substr($hex,2,1) . substr($hex,2,1) . substr($hex,3,1) . substr($hex,3,1);
}
return ((hexdec(substr($hex,1,2))+hexdec(substr($hex,3,2))+hexdec(substr($hex,5,2)) < $average) ? true : false);
}
var_dump( isDark("#000000") ); // bool(true)
?>
For example I have a blue color:
#049cd9 or rgba(4, 156, 218)
How can I calculate the correspondent color, which in this case it would be a dark blue color:
#004ea0 or rgba(0, 78, 160)
?
Normally I don't know the 2nd color (that I want to find out), so I want to find a way to get the darker color based on the first color.
Is there a formula or something that I can generate by substracting the two colors somehow?
So I've found HEX to HSL and HSL to HEX functions:
function hex_to_hue($hexcode)
{
$redhex = substr($hexcode,0,2);
$greenhex = substr($hexcode,2,2);
$bluehex = substr($hexcode,4,2);
// $var_r, $var_g and $var_b are the three decimal fractions to be input to our RGB-to-HSL conversion routine
$var_r = (hexdec($redhex)) / 255;
$var_g = (hexdec($greenhex)) / 255;
$var_b = (hexdec($bluehex)) / 255;
// Input is $var_r, $var_g and $var_b from above
// Output is HSL equivalent as $h, $s and $l — these are again expressed as fractions of 1, like the input values
$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;
} else if ($var_g == $var_max) {
$h = (1 / 3) + $del_r - $del_b;
} else if ($var_b == $var_max) {
$h = (2 / 3) + $del_g - $del_r;
}
;
if ($h < 0) {
$h += 1;
}
;
if ($h > 1) {
$h -= 1;
}
;
}
;
return array($h, $s, $l);
/*
// Calculate the opposite hue, $h2
$h2 = $h + 0.5;
if ($h2 > 1)
{
$h2 -= 1;
};
return array($h2, $s, $l);
*/
}
function hue_to_hex($hue = array())
{
function hue_2_rgb($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);
}
;
list($h2, $s, $l) = $hue;
// Input is HSL value of complementary colour, held in $h2, $s, $l as fractions of 1
// Output is RGB in normal 255 255 255 format, held in $r, $g, $b
// Hue is converted using function hue_2_rgb, shown at the end of this code
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 = 255 * hue_2_rgb($var_1,$var_2,$h2 + (1 / 3));
$g = 255 * hue_2_rgb($var_1,$var_2,$h2);
$b = 255 * hue_2_rgb($var_1,$var_2,$h2 - (1 / 3));
}
;
$rhex = sprintf("%02X",round($r));
$ghex = sprintf("%02X",round($g));
$bhex = sprintf("%02X",round($b));
return $rhex.$ghex.$bhex;
}
They work because I tested them by converting a color back and forth.
But I don't know how can I change the Hue and Luminosity properties just like in Photoshop?
The dark color would be H +13 and L -28.
And the hex_to_hsl function above returns float values between 0 and 1...
There are formulas that convert an RGB color to HSV (Hue, Saturation and Value). From the HSV you can change any of the HSV components and then convert back to RGB. I've found stuff online and done this before. Let me know if you want more details on the algorithms, I can dig them up for you if you want.
#XXXXXX represent hexa decimal number in colors for RED, GREEN and BLUE, each two characters from left to right if you increase the number it will get light, if decrease the number, it will be darker.
You need to convert the RGB value to HSL or HSV and then you can decrease the L (luma) or V (value) component as you wish and then convert back to RGB.
see this answer for example code:
RGB to HSV in PHP
The easiest way to tinker with how colours are perceived (ie, lighter, darker, brighter, duller, etc) is to convert it to HSL. There are plenty of resources online for converting RGB to HSL and back again in PHP and JavaScript. Google will find you as many implementations as you want. Then to decrease the lightness, reduce the L value (multiply by 0.75 or similar) and convert back to RGB.
function hex_to_hue($hexcode, $percent) {
$redhex = substr($hexcode, 0, 2);
$greenhex = substr($hexcode, 2, 2);
$bluehex = substr($hexcode, 4, 2);
// $var_r, $var_g and $var_b are the three decimal fractions to be input to our RGB-to-HSL conversion routine
$var_r = (hexdec($redhex)) / 255;
$var_g = (hexdec($greenhex)) / 255;
$var_b = (hexdec($bluehex)) / 255;
// Input is $var_r, $var_g and $var_b from above
// Output is HSL equivalent as $h, $s and $l — these are again expressed as fractions of 1, like the input values
$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;
} else if ($var_g == $var_max) {
$h = (1 / 3) + $del_r - $del_b;
} else if ($var_b == $var_max) {
$h = (2 / 3) + $del_g - $del_r;
}
;
if ($h < 0) {
$h += 1;
}
;
if ($h > 1) {
$h -= 1;
}
;
}
;
//return array($h, $s, $l);
// Calculate the opposite hue, $h2
$h2 = $h + $percent;
if ($h2 > 1) {
$h2 -= 1;
}
// Calculate the opposite hue, $s2
$s2 = $s + $percent;
if ($s2 > 1) {
$s2 -= 1;
}
// Calculate the opposite hue, $s2
$l2 = $l + $percent;
if ($l2 > 1) {
$l2 -= 1;
}
return array($h2, $s2, $l2);
}
Hello fellow earthlings. A quesion about RGB color and its usefulness in a simple tiny php code:
Imagine I have variable $colorA containning a valid six char color. say B1B100, a greenish natural color. Now If I would like to make a new color from that, which is, say, ten steps lighter thatn that original color, roughly.
$colorA = B1B100 // original color
php code with little color engine lightening stuff up goes here
$colorB = ?????? // original color lightened up
Is there a php ready function that KNOWS rgb colors something like
php function RGB ( input color, what to do, output color)
Where what to do could be +/- 255 values of brightness etc etc.
Is something like this already possible or am I day dreaming?
rgb-hsl($colorA, +10, $colorB);
If this does not exist, what would be the shortest code for doing this? Suggestions, code or ideas are all answers to me. Thanks.
This SO question has a full-blown PHP script that can convert a RGB to a HSL colour, and increase its H component of a HSL colour - it should be trivial to change to increase L instead.
In general if you want a lighter shade of a particular colour, the most accurate process is to convert from RGB to HSL (or HSV), change the 'L' (or 'V') value which represents lightness, and then convert back to RGB.
This will preserve the "hue", which represents where the colour sits on the spectrum, but change the "tint" (if lightening) or "shade" (if darkening) of that colour.
See http://en.wikipedia.org/wiki/HSL_and_HSV for more information.
On this website: http://www.sitepoint.com/forums/showthread.php?t=586223 they are talking about this code which is originally made by opensource Drupal. Seems to work fine in PHP!?
Now, how do I now indermingle myself with this code and change the lightness of an HSL value, before its outputted as RGB again?
<?php
### RGB >> HSL
function _color_rgb2hsl($rgb) {
$r = $rgb[0]; $g = $rgb[1]; $b = $rgb[2];
$min = min($r, min($g, $b)); $max = max($r, max($g, $b));
$delta = $max - $min; $l = ($min + $max) / 2; $s = 0;
if ($l > 0 && $l < 1) {
$s = $delta / ($l < 0.5 ? (2 * $l) : (2 - 2 * $l));
}
$h = 0;
if ($delta > 0) {
if ($max == $r && $max != $g) $h += ($g - $b) / $delta;
if ($max == $g && $max != $b) $h += (2 + ($b - $r) / $delta);
if ($max == $b && $max != $r) $h += (4 + ($r - $g) / $delta);
$h /= 6;
} return array($h, $s, $l);
}
### HSL >> RGB
function _color_hsl2rgb($hsl) {
$h = $hsl[0]; $s = $hsl[1]; $l = $hsl[2];
$m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l*$s;
$m1 = $l * 2 - $m2;
return array(_color_hue2rgb($m1, $m2, $h + 0.33333),
_color_hue2rgb($m1, $m2, $h),
_color_hue2rgb($m1, $m2, $h - 0.33333));
}
### Helper function for _color_hsl2rgb().
function _color_hue2rgb($m1, $m2, $h) {
$h = ($h < 0) ? $h + 1 : (($h > 1) ? $h - 1 : $h);
if ($h * 6 < 1) return $m1 + ($m2 - $m1) * $h * 6;
if ($h * 2 < 1) return $m2;
if ($h * 3 < 2) return $m1 + ($m2 - $m1) * (0.66666 - $h) * 6;
return $m1;
}
### Convert a hex color into an RGB triplet.
function _color_unpack($hex, $normalize = false) {
if (strlen($hex) == 4) {
$hex = $hex[1] . $hex[1] . $hex[2] . $hex[2] . $hex[3] . $hex[3];
} $c = hexdec($hex);
for ($i = 16; $i >= 0; $i -= 8) {
$out[] = (($c >> $i) & 0xFF) / ($normalize ? 255 : 1);
} return $out;
}
### Convert an RGB triplet to a hex color.
function _color_pack($rgb, $normalize = false) {
foreach ($rgb as $k => $v) {
$out |= (($v * ($normalize ? 255 : 1)) << (16 - $k * 8));
}return '#'. str_pad(dechex($out), 6, 0, STR_PAD_LEFT);
}
/* $testrgb = array(0.2,0.75,0.4); //RGB to start with
print_r($testrgb); */
print "Hex: ";
$testhex = "#b7b700";
print $testhex;
$testhex2rgb = _color_unpack($testhex,true);
print "<br />RGB: ";
var_dump($testhex2rgb);
print "<br />HSL color module: ";
$testrgb2hsl = _color_rgb2hsl($testhex2rgb); //Converteren naar HSL
var_dump($testrgb2hsl);
print "<br />RGB: ";
$testhsl2rgb = _color_hsl2rgb($testrgb2hsl); // En weer terug naar RGB
var_dump($testhsl2rgb);
print "<br />Hex: ";
$testrgb2hex = _color_pack($testhsl2rgb,true);
var_dump($testrgb2hex);
?>
PHP does have a couple image manipulation libraries. Either GD or Imagemagick
EDIT: I jumped the gun, these libraries do not have direct PHP color manipulation functions - I honestly assumed they did of a sort after seeing a lot of the things they can do with images via PHP. They do accomplish a lot of cool things. Here's one guy's example.
How would I generate a color based on what letter a string begins with - perhaps A could be blue, Z could be green and the other letters would be the gradually changing spectrum in between?
Try this function:
Generate Gradient Within Hex Range In PHP
A function that generates an array of hex colors that forms a
gradient, starting from a hex color and ending with another hex color.
The number of gradient steps can also be defined.
function Gradient($HexFrom, $HexTo, $ColorSteps)
{
$FromRGB['r'] = hexdec(substr($HexFrom, 0, 2));
$FromRGB['g'] = hexdec(substr($HexFrom, 2, 2));
$FromRGB['b'] = hexdec(substr($HexFrom, 4, 2));
$ToRGB['r'] = hexdec(substr($HexTo, 0, 2));
$ToRGB['g'] = hexdec(substr($HexTo, 2, 2));
$ToRGB['b'] = hexdec(substr($HexTo, 4, 2));
$StepRGB['r'] = ($FromRGB['r'] - $ToRGB['r']) / ($ColorSteps - 1);
$StepRGB['g'] = ($FromRGB['g'] - $ToRGB['g']) / ($ColorSteps - 1);
$StepRGB['b'] = ($FromRGB['b'] - $ToRGB['b']) / ($ColorSteps - 1);
$GradientColors = array();
for($i = 0; $i <= $ColorSteps; $i++)
{
$RGB['r'] = floor($FromRGB['r'] - ($StepRGB['r'] * $i));
$RGB['g'] = floor($FromRGB['g'] - ($StepRGB['g'] * $i));
$RGB['b'] = floor($FromRGB['b'] - ($StepRGB['b'] * $i));
$HexRGB['r'] = sprintf('%02x', ($RGB['r']));
$HexRGB['g'] = sprintf('%02x', ($RGB['g']));
$HexRGB['b'] = sprintf('%02x', ($RGB['b']));
$GradientColors[] = implode(NULL, $HexRGB);
}
return $GradientColors;
}
$Gradients = Gradient("FF5B5B", "FFCA5B", 32);
foreach($Gradients as $Gradient)
{
echo "<div style=\"background-color: #".$Gradient."; width: 100px; height: 25px;\"></div>";
}
From https://web.archive.org/web/20160915121028/http://www.geekpedia.com/code163_Generate-Gradient-Within-Hex-Range-In-PHP.html
$str = iconv("CURRENT CHARSET HERE", "ASCII//TRANSLIT", $orig_string);
$letter = ucfirst($str);
//A is 65, Z is 90
$hue = 2*pi() * ((ord($letter) - 65)/(90-65));
This is will give you the hue in radians. Then, it's just a matter of picking a certain saturation and brightness and convert to RGB or whatever. See the Wikipedia page on HSV color space and convering to RGB.
You're definitely going to want to use HSV, since it's trivial to smoothly transition from one hue to another in that space.
Probably not the most efficient code in the world, but here goes. There's a little test page at the bottom of the code which you can remove/disregard, of course.
<?php
// RGB_TO_HSV copied from http://www.actionscript.org/forums/showthread.php3?t=50746
function HSV_TO_RGB ($H, $S, $V) // HSV Values:Number 0-1
{ // RGB Results:Number 0-255
$RGB = array();
if($S == 0)
{
$R = $G = $B = $V * 255;
}
else
{
$var_H = $H * 6;
$var_i = floor( $var_H );
$var_1 = $V * ( 1 - $S );
$var_2 = $V * ( 1 - $S * ( $var_H - $var_i ) );
$var_3 = $V * ( 1 - $S * (1 - ( $var_H - $var_i ) ) );
if ($var_i == 0) { $var_R = $V ; $var_G = $var_3 ; $var_B = $var_1 ; }
else if ($var_i == 1) { $var_R = $var_2 ; $var_G = $V ; $var_B = $var_1 ; }
else if ($var_i == 2) { $var_R = $var_1 ; $var_G = $V ; $var_B = $var_3 ; }
else if ($var_i == 3) { $var_R = $var_1 ; $var_G = $var_2 ; $var_B = $V ; }
else if ($var_i == 4) { $var_R = $var_3 ; $var_G = $var_1 ; $var_B = $V ; }
else { $var_R = $V ; $var_G = $var_1 ; $var_B = $var_2 ; }
$R = $var_R * 255;
$G = $var_G * 255;
$B = $var_B * 255;
}
$RGB['R'] = $R;
$RGB['G'] = $G;
$RGB['B'] = $B;
return $RGB;
}
function getColorForWord($word) {
// get the percent of the first letter ranging from 0-1
$first_letter_code = (ord(strtolower($word[0]))-97)/25.0;
// add a phase depending on where you want to start on the color spectrum
// red is 0, green is 0.25, cyan is 0.5, blue is ~0.75, and 1 is back to red
$hue = $first_letter_code + 0.25;
// you may also want to divide by how much of the spectrum you want to cover
// (making the colors range only from green to blue, for instance)
// but i'll leave that as an exercise
// constrain it to 0-1
if ($hue > 1.0)
$hue -= 1.0;
// the second value is the saturation ("colorfulness", ranging from gray to fully-colored)
// the third is the value (brightness)
$rgb = HSV_TO_RGB($hue, 1, 0.75);
$hexstring = "#";
foreach ($rgb as $c)
$hexstring .= str_pad(dechex($c), 2, "0", STR_PAD_LEFT);
return $hexstring;
}
?>
<html>
<head>
</head>
<body>
<form method="POST" action="<?=$_SERVER["PHP_SELF"]?>">
<input type="text" name="target_word" />
<?php
if ($_REQUEST["sub"] && $_REQUEST["target_word"] != "") {
print "<span style=\"font-weight: bold; color: ".getColorForWord($_REQUEST["target_word"]).";\">".$_REQUEST["target_word"]."</span>";
}
?>
<br />
<input type="submit" name="sub" value="Colorize" />
</form>
</body>
I would specify the RGB code of the first color (100,100,100) and the RGB code of the last color (200,200,200) and basically do
1..25
B..Y
resultingR = firstR + (lastR-firstR) * (1..25/26)
resultingG = firstG + (lastG-firstG) * (1..25/26)
resultingB = firstB + (lastB-firstB) * (1..25/26)
so B would give 100 + floor((200-100) * (1 / 26))
104,104,104
and Y would be 100 + floor((200-100) * (1 / 26))
196,196,196
This is a base code, but it will allow gradient on all the 3 color, or only 1 (example 100,100,100 to 100,100,200) which would do a gradient toward Blue
I came up with this more simple solution based on the idea of converting the first six alphabetic characters (including spaces) to a relevant hexadecimal character. With the hexadecimal, it is helpful to know that (for example #123456), if you change 1 and 2, it will become more CYAN at the values toward zero, and more white towards values of F. If you change 3 and 4, it will become more MAGENTA at the values toward zero, and more white towards the value of F. If you change five and six it will become more YELLOW at the values towards zero, and more white towards values of F. After making this, I also tried to calculate the complimentary colour (good for background) using a similar strategy. But it's quite hard the middle level values in the hexadecimal become grey (7,8).
$word="word 1";
$letter = substr(strtolower($word), 0,6);
$i=0;
$hd="#";
while ($i<=5){
$l2=substr($letter,$i,1);
if($l2=="a" || $l2=="b"){$hd=$hd."0";}
elseif($l2=="c" || $l2=="d"){$hd=$hd."1";}
elseif($l2=="e"){$hd=$hd."2";}
elseif($l2=="f" || $l2=="g"){$hd=$hd."3";}
elseif($l2=="h" || $l2=="i"){$hd=$hd."4";}
elseif($l2=="j"){$hd=$hd."5";}
elseif($l2=="k" || $l2=="l"){$hd=$hd."6";}
elseif($l2=="m" || $l2=="n"){$hd=$hd."7";}
elseif($l2=="o"){$hd=$hd."8";}
elseif($l2=="p" || $l2=="q"){$hd=$hd."9";}
elseif($l2=="r" || $l2=="s"){$hd=$hd."A";}
elseif($l2=="t"){$hd=$hd."B";}
elseif($l2=="u" || $l2=="v"){$hd=$hd."C";}
elseif($l2=="w" || $l2=="x"){$hd=$hd."D";}
elseif($l2=="y"){$hd=$hd."E";}
elseif($l2=="z" || $l2==" " || $l2==""){$hd=$hd."F";}
$i++;
}
//calculating the complimentary colour
$o=1;
$comp="#";
while($o<=6){
$see=substr($hd,$o,1);
if($see=="F"){$comp=$comp."0";}
elseif($see=="E"){$comp=$comp."1";}
elseif($see=="D"){$comp=$comp."2";}
elseif($see=="C"){$comp=$comp."3";}
elseif($see=="B"){$comp=$comp."4";}
elseif($see=="A"){$comp=$comp."5";}
elseif($see=="9"){$comp=$comp."F";}
elseif($see=="8"){$comp=$comp."0";}
elseif($see=="7"){$comp=$comp."F";}
elseif($see=="6"){$comp=$comp."0";}
elseif($see=="5"){$comp=$comp."F";}
elseif($see=="4"){$comp=$comp."B";}
elseif($see=="3"){$comp=$comp."C";}
elseif($see=="2"){$comp=$comp."D";}
elseif($see=="1"){$comp=$comp."E";}
elseif($see=="0"){$comp=$comp."F";}
$o++;
}
echo" hexadecimal is $hd, complimentary colour is $comp";