Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

bjorn2404 commented Aug 22, 2017

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

@pandymic

This comment has been minimized.

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

This comment has been minimized.

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;
	}
@yethael

This comment has been minimized.

Copy link

yethael commented Nov 8, 2017

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

This comment has been minimized.

Copy link

theus commented Mar 19, 2018

Oh, great. Thank you.

@papac

This comment has been minimized.

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
You can’t perform that action at this time.