This may be a rather lengthy explanation, so bear with me. I am a little foggy on screen colour theory, so apologies if I'm asking stupid questions... here goes...

I wish to be able to write a function like so..

function fadeColour($base_colour, $percent) {

}

Then I can provide the $base_colour in standard hex (eg. #FF0000) and the $percent to fade.

So the script would work out the $percent alpha of the $base_colour (ie. mix with white) So if the $base_colour was #FF0000 and the $percent was 5 the result would be #DB201C

I've tried this in several ways, the closest I cam was to the split the hex into it's rgb components then use hexdec() to convert each colour to a decimal, subtract the $percent then re-hex it. However this just changed the colour through the spectrum rather than giving a alpha/transparency fade effect.

This is driving me mad, could someone please point me in the right direction or give me some solution? Thank you!

    I think multiplying by the fade factor would be more succesful than subtracting - that would shift it towards black however. Hmm. Subtract the colour from white (0xffffff-$rgb), break that into separate components scale that by the fade factor (actually, one minus the fade factor because 100% means a factor of 1,and you want to multiply by 0 in that case), recombine the components and subtract the resulting colour from white again.

    It might be possible to simplify that by doing a bit of arithmetic, but my caffeine system has too much blood in it right now.

    An alternative (which would be more flexible in the long run) would be to look at RGB <-> HSV conversions; then fading to white simply means pushing the V component closer to 1.

      Yeah, that's probably a good idea. I've been searching on google for rgb->hls but can't really find anything useful (or at least that I can understand) I think maybe I need a better grounding in colour theory. Can anyone point me in the right direction? Thanks.

        Did some digging around, and found some pseudocode that could be rewritten in PHP. It's no substitute for learning the theory, but if all you need is the practice, it's there.

          4 days later

          cool, cheers! I converted this to php...

          function rgbtohsv ($rgb) {
          
          $red = ( $rgb[0] / 255 );                    //RGB values = From 0 to 255
          $green = ( $rgb[1] / 255 );
          $blue = ( $rgb[2] / 255 );
          
          $min = min( $red, $green, $blue );   		//Min. value of RGB
          $max = max( $red, $green, $blue );    		//Max. value of RGB
          $delta = $max - $min;             			//Delta RGB value
          
          $V = $max;
          
          if ( $max == 0 )                     		//This is a gray, no chroma...
          {
             $H = 0;                                	//HSL results = From 0 to 1
             $S = 0;
          }
          else                                    	//Chromatic data...
          {
             if ( $L < 0.5 ) {
             		$S = $max / ( $max + $min );
          	}
             	else  {
          		$S = $max / ( 2 - $max - $min );
          	}
          
             	$delta_R = ( ( ( $max - $red ) / 6 ) + ( $max / 2 ) ) / $delta;
             	$delta_G = ( ( ( $max - $green ) / 6 ) + ( $max / 2 ) ) / $delta;
             	$delta_B = ( ( ( $max - $blue ) / 6 ) + ( $max / 2 ) ) / $delta;
          
             	if ( $red == $max ) {
             		$H = $delta_B - $delta_G;
          	}
             	else if ( $green == $max ) {
          		$H = ( 1 / 3 ) + $delta_R - $delta_B;
          	}
             	else if ( $blue == $max ) { 
          		$H = ( 2 / 3 ) + $delta_G - $delta_R;
          	}
          
             if ( $H < 0 ) { $H++; }
             if ( $H > 1 ) { $H--; }
          }
          
          echo($H." ".$S." ".$V);
          }
          
          function hsvtorgb($hsv) {
          
          $H = $hsv[0];
          $S = $hsv[1];
          $V = $hsv[2];
          
          if ( $S == 0 )                       //HSV values = From 0 to 1
          	{
          	   $red = $V * 255 ;                     //RGB results = From 0 to 255
          	   $green = $V * 255;
          	   $blue = $V * 255;
          	}
          else
          	{
          	   $var_h = $H * 6;
          	   $var_i = round( $var_h );             //Or ... 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 ) { 
          	   		$red = $V; 
          			$green = $var_3; 
          			$blue = $var_1; 
          		}
          	   	else if ( $var_i == 1 ) {
          			$red = $var_2; 
          			$green = $V; 
          			$blue = $var_1; 
          		}
          	   	else if ( $var_i == 2 ) { 
          			$red = $var_1; 
          			$green = $V; 
          			$blue = $var_3; 
          		}
          	   	else if ( $var_i == 3 ) { 
          			$red = $var_1; 
          			$green = $var_2; 
          			$blue = $V;     
          		}
          	   	else if ( var_i == 4 ) { 
          			$red = $var_3; 
          			$green = $var_1; 
          			$blue = $V;     
          		}
          	   	else { 
          			$red = $V; 
          			$green = $var_1; 
          			$blue = $var_2; 
          		}
          
          	   $red = round($red * 255) ;                 //RGB results = From 0 to 255
          	   $green = round($green * 255);
          	   $blue = round($blue * 255);
          	   }
          
          
          echo($red.", ".$green.", ".$blue);
          }
          

          However, convering rgb->hsv then back again doesn't work too well, any chance you could have a look at my code, and see if i've gone wrong anywhere? I know it's a VERY big ask, but it would be great if you could have a look. Thanks!!

            Well, it looks like a few glitches in your variable renaming for the most part: in rgbtohsv you're looking at $max instead of $delta, which causes it to go wobbly when it hits a grey. (You've also introduced a new test involving a previously-unseen "$L" that wasn't in the original algorithm. It had just $S = $delta/$max;. If you made the test in case $max was zero, note that it never will be, because if $max is zero, $min must be zero as well, and hence $delta is zero, and then that branch will never be reached.)

            I didn't see any problems with hsvtorgb on a cursory inspection, although you may find using a switch construct cleaner:

            switch($var_i)
            {
            case 0: $red = $V;     $green = $var_3; $blue = $var_1; break;
            case 1: $red = $var_2; $green = $V;     $blue = $var_1; break;
            case 2: $red = $var_1; $green = $V;     $blue = $var_3; break;
            case 3: $red = $var_1; $green = $var_2; $blue = $V;     break;
            case 4: $red = $var_3; $green = $var_1; $blue = $V;     break;
            case 5: $red = $V;     $green = $var_1; $blue = $var_2; break;
            }
            

              Yes! It works, boy do I feel stupid for missing all those errors. Thank you so much!

                Write a Reply...