mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-11-16 13:07:14 +01:00
170 lines
5.4 KiB
PHP
170 lines
5.4 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace Xentral\Components\Util;
|
||
|
|
||
|
use Xentral\Components\Util\Exception\InvalidArgumentException;
|
||
|
|
||
|
final class ColorUtil
|
||
|
{
|
||
|
/**
|
||
|
* @example '#369' or '#336699' => array('r' => 51, 'g' => 102, 'b' => 153)
|
||
|
*
|
||
|
* @param string $hexColor
|
||
|
*
|
||
|
* @throws InvalidArgumentException
|
||
|
*
|
||
|
* @return array ['r' => {$red}, 'g' => {$green}, 'b' => {$blue}]
|
||
|
*/
|
||
|
public static function convertHexToRgb($hexColor)
|
||
|
{
|
||
|
self::ensureHexColorFormat($hexColor);
|
||
|
|
||
|
$hexColor = self::normalizeHexColor($hexColor);
|
||
|
$hexColor = str_replace('#', '', $hexColor);
|
||
|
|
||
|
$colorParts = str_split($hexColor, 2);
|
||
|
$red = (int)hexdec($colorParts[0]);
|
||
|
$green = (int)hexdec($colorParts[1]);
|
||
|
$blue = (int)hexdec($colorParts[2]);
|
||
|
|
||
|
return ['r' => $red, 'g' => $green, 'b' => $blue];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $red [0-255]
|
||
|
* @param int $green [0-255]
|
||
|
* @param int $blue [0-255]
|
||
|
*
|
||
|
* @throws InvalidArgumentException
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public static function convertRgbToHex($red, $green, $blue)
|
||
|
{
|
||
|
if ($red < 0 || $red > 255) {
|
||
|
throw new InvalidArgumentException(sprintf(
|
||
|
'Invalid value for color red "%s". Color values must be between 0 and 255.', $red
|
||
|
));
|
||
|
}
|
||
|
if ($green < 0 || $green > 255) {
|
||
|
throw new InvalidArgumentException(sprintf(
|
||
|
'Invalid value for color green "%s". Color values must be between 0 and 255.', $green
|
||
|
));
|
||
|
}
|
||
|
if ($blue < 0 || $blue > 255) {
|
||
|
throw new InvalidArgumentException(sprintf(
|
||
|
'Invalid value for color blue "%s". Color values must be between 0 and 255.', $blue
|
||
|
));
|
||
|
}
|
||
|
|
||
|
$rHex = StringUtil::padLeft(dechex($red), 2, '0');
|
||
|
$gHex = StringUtil::padLeft(dechex($green), 2, '0');
|
||
|
$bHex = StringUtil::padLeft(dechex($blue), 2, '0');
|
||
|
$hexColor = '#' . strtoupper($rHex . $gHex . $bHex);
|
||
|
self::ensureHexColorFormat($hexColor);
|
||
|
|
||
|
return $hexColor;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Normalizes hex colors
|
||
|
*
|
||
|
* - Transforms shorthand hexcolors (e.g. #369) into long hexcolor format (#336699)
|
||
|
* - Long hexcolor format (#336699) will be unchanged
|
||
|
*
|
||
|
* @param string $hexColor
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public static function normalizeHexColor($hexColor)
|
||
|
{
|
||
|
self::ensureHexColorFormat($hexColor);
|
||
|
|
||
|
$hexColor = str_replace('#', '', $hexColor);
|
||
|
|
||
|
if (strlen($hexColor) === 3) {
|
||
|
$red = !empty($hexColor[0]) ? $hexColor[0] : '0';
|
||
|
$green = !empty($hexColor[1]) ? $hexColor[1] : '0';
|
||
|
$blue = !empty($hexColor[2]) ? $hexColor[2] : '0';
|
||
|
|
||
|
$hexColor = $red . $red . $green . $green . $blue . $blue;
|
||
|
}
|
||
|
|
||
|
return '#' . $hexColor;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Calculates the brightness level (YIQ formula); is the given color more darker or lighter?
|
||
|
*
|
||
|
* Result 'dark' means: The given color is more darker than light. When using the given color as
|
||
|
* a background color, then use a light text color for better contrast (and vice versa).
|
||
|
*
|
||
|
* @param int $red [0-255]
|
||
|
* @param int $green [0-255]
|
||
|
* @param int $blue [0-255]
|
||
|
*
|
||
|
* @throws InvalidArgumentException
|
||
|
*
|
||
|
* @return string [dark|light]
|
||
|
*/
|
||
|
public static function calculateBrightnessLevel($red, $green, $blue)
|
||
|
{
|
||
|
if ($red < 0 || $red > 255) {
|
||
|
throw new InvalidArgumentException(sprintf(
|
||
|
'Invalid value for color red "%s". Color values must be between 0 and 255.', $red
|
||
|
));
|
||
|
}
|
||
|
if ($green < 0 || $green > 255) {
|
||
|
throw new InvalidArgumentException(sprintf(
|
||
|
'Invalid value for color green "%s". Color values must be between 0 and 255.', $green
|
||
|
));
|
||
|
}
|
||
|
if ($blue < 0 || $blue > 255) {
|
||
|
throw new InvalidArgumentException(sprintf(
|
||
|
'Invalid value for color blue "%s". Color values must be between 0 and 255.', $blue
|
||
|
));
|
||
|
}
|
||
|
|
||
|
/** @see http://dannyruchtie.com/color-contrast-calculator-with-yiq/ */
|
||
|
$yiqValue = ($red * 299 + $green * 587 + $blue * 114) / 1000;
|
||
|
|
||
|
return $yiqValue >= 128 ? 'light' : 'dark';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $hexColor
|
||
|
*
|
||
|
* @throws InvalidArgumentException
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
private static function ensureHexColorFormat($hexColor)
|
||
|
{
|
||
|
if (strpos($hexColor, '#') !== 0) {
|
||
|
throw new InvalidArgumentException(sprintf(
|
||
|
'Invalid format for hex color "%s". Hex color must start with hash char (#).',
|
||
|
$hexColor
|
||
|
));
|
||
|
}
|
||
|
|
||
|
$hexString = substr_replace($hexColor, '', 0, 1);
|
||
|
$hexCleaned = preg_replace('/[^0-9A-Fa-f]/', '', $hexString);
|
||
|
if ($hexString !== $hexCleaned) {
|
||
|
throw new InvalidArgumentException(sprintf(
|
||
|
'Invalid format for hex color "%s". Hex color contains invalid chars. ' .
|
||
|
'Valid chars are: A-F, a-f and 0-9.',
|
||
|
$hexColor
|
||
|
));
|
||
|
}
|
||
|
|
||
|
$hexColorLength = strlen($hexColor);
|
||
|
if ($hexColorLength !== 4 && $hexColorLength !== 7) {
|
||
|
throw new InvalidArgumentException(sprintf(
|
||
|
'Invalid format for hex color "%s". Hex color must be four or seven chars long; ' .
|
||
|
'with leading hash char (#).',
|
||
|
$hexColor
|
||
|
));
|
||
|
}
|
||
|
}
|
||
|
}
|