Skip to content

Instantly share code, notes, and snippets.

@stephenharris
Created May 7, 2013 14:19
Show Gist options
  • Star 37 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save stephenharris/5532899 to your computer and use it in GitHub Desktop.
Save stephenharris/5532899 to your computer and use it in GitHub Desktop.
Lighten or darken a given colour
<?php
/**
* Lightens/darkens a given colour (hex format), returning the altered colour in hex format.7
* @param str $hex Colour as hexadecimal (with or without hash);
* @percent float $percent Decimal ( 0.2 = lighten by 20%(), -0.4 = darken by 40%() )
* @return str Lightened/Darkend colour as hexadecimal (with hash);
*/
function color_luminance( $hex, $percent ) {
// validate hex string
$hex = preg_replace( '/[^0-9a-f]/i', '', $hex );
$new_hex = '#';
if ( strlen( $hex ) < 6 ) {
$hex = $hex[0] + $hex[0] + $hex[1] + $hex[1] + $hex[2] + $hex[2];
}
// convert to decimal and change luminosity
for ($i = 0; $i < 3; $i++) {
$dec = hexdec( substr( $hex, $i*2, 2 ) );
$dec = min( max( 0, $dec + $dec * $percent ), 255 );
$new_hex .= str_pad( dechex( $dec ) , 2, 0, STR_PAD_LEFT );
}
return $new_hex;
}
@bjorn2404
Copy link

Nice, it doesn't seem to work for straight black though #000000.

@pandymic
Copy link

pandymic commented Aug 29, 2017

@bjorn2404: Nice, it doesn't seem to work for straight black though #000000.

This is working as intended. Adjusting the luminescence of a color value lightens or darkens it by a percentage factor of itself. Any percentage increase of solid black ( RGB 0, 0, 0) will result in zero.

I suspect what you're trying to to is change the tint of the black and bring it into a gray/white space? This would require a different function altogether.

@regularlabs
Copy link

regularlabs commented Sep 16, 2017

This is a different approach.
It expects and returns an array of the rbg color values, like array(0, 100, 255).
But you can of course create your own simple decimal to hex converter in there.

	// 0% =  black
	// 50% = no change
	// 100% = white
	function luminate($color, $percent)
	{
		foreach ($color as &$value)
		{
			$value = min(max(0, self::luminateValue($value, $percent)), 255);
		}

		return $color;
	}

	function luminateValue($value, $percent)
	{
		// no change
		if ($percent == 50)
		{
			return $value;
		}

		// ratio = value from 0 to 2
		$ratio = $percent * 2 / 100;

		// darken color
		if ($percent < 50)
		{
			return $value * $ratio;
		}

		// lighten color

		// reverse ratio
		$ratio = 2 - $ratio;

		$diff  = (255 - $value) * $ratio;

		return 255 - $diff;
	}

@jeanchernandez
Copy link

This works for me:

function luminance($hexcolor, $percent)
{
  if ( strlen( $hexcolor ) < 6 ) {
    $hexcolor = $hexcolor[0] . $hexcolor[0] . $hexcolor[1] . $hexcolor[1] . $hexcolor[2] . $hexcolor[2];
  }
  $hexcolor = array_map('hexdec', str_split( str_pad( str_replace('#', '', $hexcolor), 6, '0' ), 2 ) );

  foreach ($hexcolor as $i => $color) {
    $from = $percent < 0 ? 0 : $color;
    $to = $percent < 0 ? $color : 255;
    $pvalue = ceil( ($to - $from) * $percent );
    $hexcolor[$i] = str_pad( dechex($color + $pvalue), 2, '0', STR_PAD_LEFT);
  }

  return '#' . implode($hexcolor);
}

@theus
Copy link

theus commented Mar 19, 2018

Oh, great. Thank you.

@papac
Copy link

papac commented Jul 20, 2018

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment