Change brightness of a color?

I wonder how I make a php function that can alter a color’s brightness if it is too strong.

I know how to get the brightness, I have made a function for it:

<? function GET_BRIGHTNESS($hexcolor)
(
/ / HEX > RGB
$ R = hexdec(substr($hexcolor, 0.2));
$ G = hexdec(substr($hexcolor, 2.2));
$ B = hexdec(substr($hexcolor, 4.2));

/ *
Counting out a number from 0 to 765 where 0 is no brightness
at all and 765 is the maximum brightness.
* /
$brightness = $R+$G+$B;

return($brightness);
)
?>

But I also have a function that can find the closest shade that is within the maximum and minimum limits I decided the brightness will have to have. Like a function that can be used as follows:

changeBrightness('64bfd9 ',‘0-500’);

Color brightness may just be somewhere between 100 to 765. And if the color is too light / dark, the closest color will be chosen.

Is there anyone who knows if this is possible, and if so, how?

I can say this to be used to a website where I have to be able to bring a background color behind a white text. Even if the shade is exactly the same position in the color palette, it may have different intensities, which complicate the contrast against the white text. I have functions that can change shades of colour but they unfortunately do not know if a color is too strong brightness.

I am sure you aren’t the only person thinking about this problem, a search of google php code throws up reference to a hexshifter() function which might inspire you.

I’d love to work out how to do the equivalent of bit-shifting in hex, but I bet someone’s already chased it down. I’d be specially interested in how you wind down each of the values by a percentage, so the whole thing gets less light ( or greyer ) rather than taking each value down by a set amount.

I couldn’t find any hexshifter() function? And I don’t really understand the rest of what you tell.

You would have to click on one of the links to see it.

the hexcolorshifter function works almost exactly as the function I already had done?

My thoughts on how the function will work is that the function examines the brightness of all the colors that are around the specified color in the color palette and engaged outward until it finds a color with a brightness which is within the specified brightness values

But I do not know how this should be done with php. Some tips?

Perhaps the color contrast algorithm may help you.
http://www.w3.org/TR/AERT#color-contrast

Color brightness is determined by the following formula:
((Red value X 299) + (Green value X 587) + (Blue value X 114)) / 1000
Note: This algorithm is taken from a formula for converting RGB values to YIQ values. This brightness value gives a perceived brightness for a color.

Okay, so even a way to find out the brightness? But still, how do I CHANGE a color to a nearby color with better brightness?

Find the brightness, find the difference of the desired level, then add the difference to each value. While keeping in RGB range. 0-255

Question 1: How do I do the loop in php?
Question 2: If an RGB value is 0, how do I prevent it to get minusvalue?

Jerrett Taylor at Bravenet used to have a ColorMatch class that did all of this stuff. He took down most of his sites several years ago, and I haven’t been able to find the script since then.

Rough…extremely rough.
adjustment brightness scale: 0 = black, 765 = white


<?php // sp bug fix &#37; 

function changeBrightness ( $hex, $adjust )
{
    $red   = hexdec( $hex[0] . $hex[1] );
    $green = hexdec( $hex[2] . $hex[3] );
    $blue  = hexdec( $hex[4] . $hex[5] );

    $cb = $red + $green + $blue;

    if ( $cb > $adjust ) {
        $db = ( $cb - $adjust ) % 255;

        $red -= $db; $green -= $db; $blue -= $db;
        if ( $red < 0 ) $red = 0;
        if ( $green < 0 ) $green = 0;
        if ( $blue < 0 ) $blue = 0;
    } else {
        $db = ( $adjust - $cb ) % 255;

        $red += $db; $green += $db; $blue += $db;
        if ( $red > 255 ) $red = 255;
        if ( $green > 255 ) $green = 255;
        if ( $blue > 255 ) $blue = 255;
    }

    return str_pad( dechex( $red ), 2, '0', 0 )
         . str_pad( dechex( $green ), 2, '0', 0 )
         . str_pad( dechex( $blue ), 2, '0', 0 );
}

var_dump( changeBrightness( 'cc0000', 125 ) );

print '<span style="color: #CC0000">TestColor!<br></span>';
print '<span style="color: #' . changeBrightness( 'cc0000', 125 ) . '">TestColor!<br></span>';


I think it works! Now I must try to understand the whole function also :slight_smile:
Thank you!

Or, something is wrong. I tried the color fff600. adjust 100 gave a dark yellow color. 200 gave a brighter color and 300 gave a really dark color. The best thing would be if you could send a brightness maximum and minimum limit to the function.

Perhaps this?

<?

/** 
* ColorMatch class
* Version       : 1.0
* Author        : Jerrett Taylor
* Last Updated  : March 1, 2003
*/

class ColorMatch
{
    var $default_color = '';
    var $colors = Array();
    
    /**
    * Constructor. Generates matching colors if passed a color
    */
    function ColorMatch($_color='')
    {
        // Constructor. If passed a color, generate our matching colors
        if ($_color) $this->Generate($_color);    
    }
    
    /**
    * returns requested color,or default if color is invalid
    * @param $_type type of color to return
    * @param $_pos position/number of color to return
    * @returns hexidecimal color
    */
    function GetColor($_type,$_pos)
    {
        return ($this->colors[$_type][$_pos]) ? $this->colors[$_type][$_pos] : $this->default_color;
    }
    
    /**
    * converts a hexidecimal color to HSV Color Model
    * @param $hex hexidecimal color
    * @returns array( hue, saturation, value )
    */
    function hex2hsv ($_hex)
    {
        $rgb = hexdec(str_replace("#","",$_hex));
        list ($_red,$_green,$_blue) = array(($rgb >> 16) & 0xFF, ($rgb >> 8) & 0xFF, $rgb & 0xFF);
    
        // get highest and lowest colors
        $max = max($_red,$_green,$_blue);
        $min = min($_red,$_green,$_blue);
        
        $v = $max;          // 'value' is always the highest value from RGB
        $delta = $max-$min; // get midway between highest and lowest, this is our delta!
        if ($max == 0)  return Array('0','0','0'); // this is black, if the biggest value is 0
    
        $s = 100*($delta/$max);  // 'saturation' is our delta divided by max 
        
        // see which color is most dominant
        if ($_red == $max)          $h = @round(( $_green - $_blue ) / $delta);     // between yellow & magenta
        elseif ($_green == $max)    $h = @round(2 + ( $_blue - $_red ) / $delta);   // between cyan & yellow
        else                        $h = @round(4 + ( $_red - $_green ) / $delta);  // between magenta & cyan
    
        $h*=60; // move into primary/secondary color group
        
        // we can't be having negatives.. if it's in negatives, add 360 (full circle)
        $h = ($h < 0) ? $h+=360 : $h;
        return Array(ceil($h),ceil($s),ceil(100*($v/255)));
    }
    
    /** 
    * converts a HSV color to hexidecimal 
    * @param $_hue HSV Hue
    * @param $_sat HSV saturation
    * @param $_val HSV value
    * @returns hexidecimal color (with #)
    */
    function hsv2hex($_hue, $_sat, $_val) 
    {
        // safegaurds against invalid values
        if ($_hue < 0 ) $_hue+=359; elseif ($_hue > 359) $_hue-=359;
        if ($_val > 100) $_val=100; elseif ($_val < 0) $_val = 0; 
        if ($_sat > 100) $_sat=100; elseif ($_sat < 0) $_sat=0;
        if ($_sat == 0) { $_val = floor($_val*2.55);     return '#'.str_pad(dechex($_val),2,'0',STR_PAD_LEFT).str_pad(dechex($_val),2,'0',STR_PAD_LEFT).str_pad(dechex($_val),2,'0',STR_PAD_LEFT); } // this is grey
    
        $_hue/=60;              // move hue into 1-6 (primary & secondary colors)
        $_sat/=100; $_val/=100; // divide by 100 so we are dealing with proper 0.0 - 0.1 
        $factor = $_hue-floor($_hue); // get fractional part of the hue
    
        // math to get into the 255 range of things from the _sat and _val
        $color1 = ceil($_val * (1-$_sat)*255);
        $color2 = ceil($_val * (1-($_sat * $factor))*255);
        $color3 = ceil($_val * (1-($_sat * (1-$factor)))*255);
        $_val = ceil($_val*255);
    
        // return rgb based on which primary/secondary color group we are in
        switch (floor($_hue))
        {
            case 0: $red = $_val; $green = $color3; $blue = $color1; break;
            case 1: $red = $color2; $green = $_val; $blue = $color1; break;
            case 2: $red = $color1; $green = $_val; $blue = $color3; break;
            case 3: $red = $color1; $green = $color2; $blue = $_val; break;
            case 4: $red = $color3; $green = $color1; $blue = $_val; break;
            case 5: $red = $_val; $green = $color1; $blue = $color2; break;
        }
        return '#'.str_pad(dechex($red),2,'0',STR_PAD_LEFT).str_pad(dechex($green),2,'0',STR_PAD_LEFT).str_pad(dechex($blue),2,'0',STR_PAD_LEFT);
    }
    
    /**
    * Gets matching colors. Returns triad colors, complementary colors, Analog colors
    * as well as modifications to the color tint, shade, and saturation.
    * @param $_hex hexidecimal color
    */
    function Generate($_hex)
    {
        $this->default_color = $_hex;
        list($_hue,$_sat,$_val) = $this->hex2hsv($_hex);
        
        // complementary color, and 2 variations in sat/val
        $this->colors['complimentary'][1] = $this->hsv2hex($_hue-180,$_sat,$_val);
        $this->colors['complimentary'][2] = $this->hsv2hex($_hue-180,$_sat+10,$_val-20);
        $this->colors['complimentary'][3] = $this->hsv2hex($_hue-180,$_sat-50,$_val-50);
        
        // triad colors
        $this->colors['triad'][1] = $_hex;
        $this->colors['triad'][2] = $this->hsv2hex($_hue-120,$_sat,$_val);
        $this->colors['triad'][3] = $this->hsv2hex($_hue+120,$_sat,$_val);
        
        // set some vars for modification
        $hue = $_hue-45;
        $val = ($_val > 75) ? $_val-=25 : $_val;
        $val = ($val < 25)  ? $val+=25 : $_val;
        $sat = $_sat;
        
        // get us some colors!
        for ($i=1;$i<=5;$i++)
        {
            $sat-=15; $val+=5; $hue+=30;    // Move along the hsv "color sphere" thingamagig
            $this->colors['analogue'][$i]       = $this->hsv2hex($hue,$_sat,$_val);
            $this->colors['tint'][$i]         = $this->hsv2hex($_hue,$_sat,$val);

            $this->colors['shade'][$i]        = $this->hsv2hex($_hue,$sat,$_val);
            $this->colors['saturation'][$i]   = $this->hsv2hex($_hue,$sat,$val);
        }
        
        // this is a set built from the sat, tint and analog results. 
        // this could be usefull for generating a theme
        $this->colors['set'][1] = $_hex;
        $this->colors['set'][2] = $this->colors['saturation'][5];
        $this->colors['set'][3] = $this->colors['saturation'][4];
        $this->colors['set'][4] = $this->colors['tint'][5];
        $this->colors['set'][5] = $this->colors['tint'][3];
        $this->colors['set'][6] = $this->colors['tint'][1];
        $this->colors['set'][7] = $this->colors['analogue'][3];    
        $this->colors['set'][8] = $this->colors['analogue'][5]; 
    }
    
    /**
    * Dumps out a list of all available colors. 
    */
    function ShowColors()
    {
     echo '<style type="text/css">body { background-color:'.$_POST['color'].'}</style>';		
	 echo '<span style="position: absolute; top: 90px; left:15px; width: 190px;">';
        foreach($this->colors as $block => $cblock) 
        {
            echo '<span style="height: 10px; width: 190px;"> </span>';
            foreach($cblock as $key =>  $color)
            {
                echo '<span style="width: 190px;">
                    <span style="width: 110px; border: 1px solid black; border-right: 0px; display: table-cell; color: #0000ff;padding: 4px; font: 10px verdana; color:#000; background-color:#FFF; font-weight:bold;">'.$block.' '.$key.' </span>
                    <span style="width: 70px; display: table-cell; border: 1px solid black; padding: 4px; background-color: '.$color.'; text-align:center;font: 10px verdana;  color: #000;  text-transform: uppercase;">'.$color.'</span>
                </span>';    
            }
        }
        echo '</span>';    
    }
}
?>

I don’t have so much experience of classes. How will this class be used?

Okej I think I get it now.

Like this:

$instansvariabel = new ColorMatch('c0ff00');
$instansvariabel->ShowColors();

Okey, so I’ve got a collection of colors. Now what? How do I adjust the brightness of one color with this class?

I have set up a small sketch of how I thought that the function could work. What do you think? Would this function give the result I’m looking for? How will the function look like?

function setBrightness($hex,$bn_min,$bn_max)
{
// Step 1. Get RGB values
// Step 2. Get brightness of the common RGB values
// Step 3. Is the brightness of the RGB values more than $bn_max? / less than $bn_min?
// Step 4. Subtract/add to the separate RGB values until the common RGB values are within the $bn_min - $bn_max values.
// Step 5. Convert to HEX and return color-code
}

Okay, now I have developed the function a little. The only thing missing now is these loops to be adding or subtracting the RGB values. Please can I get help with them?

function setBrightness($hex,$bn_min,$bn_max)
{
// Step 1. Get RGB values
$R = hexdec(substr($hexcolor,0,2));
$G = hexdec(substr($hexcolor,2,2));
$B = hexdec(substr($hexcolor,4,2));
// Step 2. Get brightness of the common RGB values
$RGBbrightness = $R+$G+$B;

	// Step 3. Is the brightness of the RGB values more than $bn_max? / less than $bn_min?
	if ($RGBbrightness > $bn_max)
	{
	// Step 3.1 Subtract/add the separate RGB values until the common RGB values are within the $bn_min - $bn_max values.
	$R =
	$G =
	$B =
	}
	elseif ($RGBbrightness < $bn_min)
	{
	$R =
	$G =
	$B =
	}

// Step 4. Convert to HEX and return color-code
return sprintf('%02X%02X%02X', $R, $G, $B);
}

very nice to read these discussions.Because I am new to this PHP.By these discussions I got good knowledge about this PHP…