I want to convert an RGBA value to HEX in PHP. I have found good help for RGB to HEX (e.g. Convert RGB to hex color values in PHP). Now I have made an attempt to change the A value as well (e.g rgba(80,80,80,0.5) to maybe #D3D3D3 (6 digits)). Assuming, of course, that the background is white.
Below the attempt. Does anyone have any tips on how I could do this better? How do I get a matching colour but lighter?
public static function convertRGBAtoHEX6(string $rgba): string
{
if ( strpos( $rgba, '#' ) === 0 ) {
return $rgba;
}
preg_match( '/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i', $rgba, $by_color );
if(isset($by_color[4]))
{
$by_color[4] = 2 - $by_color[4];
$by_color[1] = $by_color[1] * $by_color[4];
$by_color[2] = $by_color[2] * $by_color[4];
$by_color[3] = $by_color[3] * $by_color[4];
}
return sprintf( '#%02x%02x%02x', $by_color[1], $by_color[2], $by_color[3] );
}
I came up with this solution:
See: https://3v4l.org/ick2o
The result is:
"#a7a7a7".The code is basically the same as yours with the exception of the
blendChannels()function and I got rid of that horrible regular expression.The
blendChannels()function takes the needed amount from the two supplied channels. If alpha is 1.0 the output is equal to channel 1, if alpha is 0.0 the outout is equal to channel 2, and if alpha is 0.5 an equal amount is taken from both channels. Do this for all 3 channels and you're done.As mentioned by Sammitch, in a comment, the sRGB color space is not linear. To get the best results the
blendChannels()function should take this into account:You can change the gamma to whatever you need.
You can see the difference between the various calculations best as a gradient, in this case blending black and white with a variable alpha value.
The difference between Linear and Quadratic is fairly stark, and demonstrates part of the reason for this approach, in that our eye distinguishes subtle differences better in brighter colors than darker. The Gamma correction is quite subtle in the gradient, but would likely be more apparent when applied to images.