Skip to content

Instantly share code, notes, and snippets.

@teknikqa
Created May 28, 2019 08:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save teknikqa/231b65be6877d80bd0ca02cd42295cca to your computer and use it in GitHub Desktop.
Save teknikqa/231b65be6877d80bd0ca02cd42295cca to your computer and use it in GitHub Desktop.
Find the appropriate color that works best on a given background color.
<?php
/**
* @file
* Find the appropriate color that works best on a given background color.
*/
/**
* Convert the standard RGB color to linear RGB.
*
* Returns a linear color based on the formula mentioned in
* https://www.w3.org/TR/WCAG20/#relativeluminancedef.
*/
function convert_standard_color_to_linear($color) {
if ($color <= 0.03928) {
return $color / 12.92;
}
else {
return pow(($color + 0.055) / 1.055, 2.4);
}
}
/**
* Convert a HEX value to RGB.
*
* @param string $hexStr
* The hex value to convert.
* @param bool $returnAsString
* Whether to return this as a string.
* @param string $seperator
* The character that will be used to separate the values.
*
* @return string
* The converted value in RGB.
*/
function hex2_rgb($hexStr, $returnAsString = FALSE, $seperator = ',') {
// Gets a proper hex string.
$hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr);
$rgbArray = array();
if (strlen($hexStr) == 6) {
// If a proper hex code, convert using bitwise operation. No overhead and is
// faster.
$colorVal = hexdec($hexStr);
$rgbArray['red'] = 0xFF & ($colorVal >> 0x10);
$rgbArray['green'] = 0xFF & ($colorVal >> 0x8);
$rgbArray['blue'] = 0xFF & $colorVal;
}
elseif (strlen($hexStr) == 3) {
// If shorthand notation, need some string manipulations.
$rgbArray['red'] = hexdec(str_repeat(substr($hexStr, 0, 1), 2));
$rgbArray['green'] = hexdec(str_repeat(substr($hexStr, 1, 1), 2));
$rgbArray['blue'] = hexdec(str_repeat(substr($hexStr, 2, 1), 2));
}
else {
// Invalid hex color code.
return FALSE;
}
return $returnAsString ? implode($seperator, $rgbArray) : $rgbArray;
}
/**
* Calculate the inverse color given a hex value.
*
* @param string $hex
* The hex value to invert.
* @param bool $bw
* Whether to invert to only black or white.
* @param bool $strict
* Set this to TRUE to find colors that match W3C guidelines.
*
* @return bool|string
* Reurns FALSE if invalid hex code, else returns the inverted color in RGB.
*/
function invert_color($hex, $bw = FALSE, $strict = FALSE) {
// Gets a proper hex string.
$hex = preg_replace("/[^0-9A-Fa-f]/", '', $hex);
if ($hex[0] == '#') {
$hex = substr($hex, 1);
}
// If this is a proper hex code, convert using bitwise operation. This has no
// overhead and is faster.
if (strlen($hex) == 6) {
$hex = hexdec($hex);
$r = 0xFF & ($hex >> 0x10);
$g = 0xFF & ($hex >> 0x8);
$b = 0xFF & $hex;
}
// If the value is in shorthand notation, we need to do some string
// manipulations.
elseif (strlen($hex) == 3) {
$r = hexdec(str_repeat(substr($hexStr, 0, 1), 2));
$g = hexdec(str_repeat(substr($hexStr, 1, 1), 2));
$b = hexdec(str_repeat(substr($hexStr, 2, 1), 2));
}
// Invalid hex color code.
else {
return FALSE;
}
// If $strict is set, then the inverted colors will be black or white.
if ($strict == TRUE) {
// Based on the answer provided in this StackOverflow question
// https://stackoverflow.com/a/3943023/112731
$sRGB = [$r / 255, $g / 255, $b / 255];
$lRGB = array_map("convert_standard_color_to_linear", $sRGB);
$luminosity = 0.2126 * $lRGB[0] + 0.7152 * $lRGB[1] + 0.0722 * $lRGB[2];
// $intensity should be > 186;
return ($luminosity > 0.179)
? '#000000'
: '#FFFFFF';
}
if ($bw == TRUE) {
// Based on the answer provided in this StackOverflow question
// https://stackoverflow.com/a/3943023/112731
$intensity = $r * 0.299 + $g * 0.587 + $b * 0.114;
// $intensity should be > 186;
return ($intensity > 186)
? '#000000'
: '#FFFFFF';
}
// Invert color components.
$r = (string) dechex((float) 255 - $r);
$g = (string) dechex((float) 255 - $g);
$b = (string) dechex((float) 255 - $b);
// Pad each value with leading zeros if required.
$r = str_pad($r, 2, '0', STR_PAD_LEFT);
$g = str_pad($g, 2, '0', STR_PAD_LEFT);
$b = str_pad($b, 2, '0', STR_PAD_LEFT);
return "#" . $r . $g . $b;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment