faqts : Computers : Programming : Languages : PHP : Common Problems

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

6 of 6 people (100%) answered Yes
Recently 2 of 2 people (100%) answered Yes


How can I create a color a shade darker than a given hex value?

May 27th, 2002 10:40
Pekka Saarinen, Nathan Wallace, Phil Driscoll

Extract the individual colour components using & and shifts, multiply 
a suitable factor (eg 0.9) then recombine
  $Red=intval((($Color & 0xFF0000)>>16)*0.9);
  $Green=intval((($Color & 0xFF00)>>8)*0.9);
  $Blue=intval(($Color & 0xFF)*0.9);
Someone who understands operator precidence better than I do could
probably lose a few brackets. There's also probably some cute trick
which does the entire job in one shot.
(P.S.) The above example works, but produces strong color 
hue shifts. 
The  following code converts HEX to RGB, multiplies each color channel 
and converts back to HEX. This way the hue stays correct. The function 
could of course have been written in more concise manner, but as I'm 
only learning PHP more deeply, I like to write code that even I can 
understand :)
function hexcolorshifter($color,$amount)
	$r = hexdec(substr($color, 0, 2));
	$g = hexdec(substr($color, 2, 2));
	$b = hexdec(substr($color, 4, 2));
	$new_r = abs(intval($r*$amount)); if ($new_r>255) $new_r=255;
	$new_g = abs(intval($g*$amount)); if ($new_g>255) $new_g=255;
	$new_b = abs(intval($b*$amount)); if ($new_b>255) $new_b=255;
	$hex_r =  sprintf("%02X",$new_r);
	$hex_g =  sprintf("%02X",$new_g);
	$hex_b =  sprintf("%02X",$new_b);
	// print line is only for debugging:
	// print " R:" . $new_r  . "," .  $hex_r . " G:" . 
$new_g . "," .  $hex_g . " B:" . $new_b  . "," .  $hex_b . "<br>";
	$color = $hex_r .$hex_g .$hex_b;
	return $color;
Use it like this:
$my_bg_color = hexcolorshifter($my_bg_color,".8");
If you brighten a color, each channel will clip at 255, so in 
situations where you have light source color you will most likely have 
hue shifts if channels don't clip 'equally'.