Luminosity Contrast algorithm
I think the best way is the Luminosity Contrast
algorithm:
function getContrastColor($hexColor)
{
// hexColor RGB
$R1 = hexdec(substr($hexColor, 1, 2));
$G1 = hexdec(substr($hexColor, 3, 2));
$B1 = hexdec(substr($hexColor, 5, 2));
// Black RGB
$blackColor = "#000000";
$R2BlackColor = hexdec(substr($blackColor, 1, 2));
$G2BlackColor = hexdec(substr($blackColor, 3, 2));
$B2BlackColor = hexdec(substr($blackColor, 5, 2));
// Calc contrast ratio
$L1 = 0.2126 * pow($R1 / 255, 2.2) +
0.7152 * pow($G1 / 255, 2.2) +
0.0722 * pow($B1 / 255, 2.2);
$L2 = 0.2126 * pow($R2BlackColor / 255, 2.2) +
0.7152 * pow($G2BlackColor / 255, 2.2) +
0.0722 * pow($B2BlackColor / 255, 2.2);
$contrastRatio = 0;
if ($L1 > $L2) {
$contrastRatio = (int)(($L1 + 0.05) / ($L2 + 0.05));
} else {
$contrastRatio = (int)(($L2 + 0.05) / ($L1 + 0.05));
}
// If contrast is more than 5, return black color
if ($contrastRatio > 5) {
return '#000000';
} else {
// if not, return white color.
return '#FFFFFF';
}
}
// Will return '#FFFFFF'
echo getContrastColor('#FF0000');
Some results:
NOTE: The font color is determined by the previous function. The number in brackets is the contrast ratio.
YIQ algorithm (less precise)
Another simpliest and less precise way called YIQ
(because it converts the RGB color space into YIQ):
public function getContrastColor($hexcolor)
{
$r = hexdec(substr($hexcolor, 1, 2));
$g = hexdec(substr($hexcolor, 3, 2));
$b = hexdec(substr($hexcolor, 5, 2));
$yiq = (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
return ($yiq >= 128) ? 'black' : 'white';
}