Skip to content

Commit

Permalink
Refactor Color.php for better readability and logic
Browse files Browse the repository at this point in the history
The Color.php file was refactored to improve readability and streamline its logic. Color calculations are now separated into distinct methods and redundant code was eliminated. The changes also include reordering class methods for consistent access modifiers.
  • Loading branch information
renfordt committed Mar 31, 2024
1 parent 57b2086 commit b7960ee
Showing 1 changed file with 112 additions and 122 deletions.
234 changes: 112 additions & 122 deletions src/Color.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,40 @@ public static function RGBToHSL(int $red, int $green, int $blue): array
return array(round($hue), round($saturation, 2), round($lightness, 2));
}

/**
* Calculate the components Chroma, Value, and Hue based on RGB color.
*
* @param int $red The red component of the RGB color (0-255).
* @param int $green The green component of the RGB color (0-255).
* @param int $blue The blue component of the RGB color (0-255).
* @return array An array containing the calculated values (maxRGB, minRGB, chroma, value, hue).
*/
public static function calculateCVH(int $red, int $green, int $blue): array
{
$normalizedRed = $red / 255;
$normalizedGreen = $green / 255;
$normalizedBlue = $blue / 255;

$maxRGB = max($normalizedRed, $normalizedGreen, $normalizedBlue);
$minRGB = min($normalizedRed, $normalizedGreen, $normalizedBlue);
$chroma = $maxRGB - $minRGB;
$value = $maxRGB; // also called brightness
if ($chroma == 0) {
$hue = 0;
} elseif ($maxRGB == $normalizedRed) {
$hue = 60 * (($normalizedGreen - $normalizedBlue) / $chroma);
} elseif ($maxRGB == $normalizedGreen) {
$hue = 60 * (2 + ($normalizedBlue - $normalizedRed) / $chroma);
} else {
$hue = 60 * (4 + ($normalizedRed - $normalizedGreen) / $chroma);
}

if ($hue < 0) {
$hue += 360;
}
return array($maxRGB, $minRGB, $chroma, $value, $hue);
}

/**
* Convert RGB color to HSV color space.
*
Expand Down Expand Up @@ -117,39 +151,48 @@ public static function RGBToHSV(int $red, int $green, int $blue): array
*/
public static function HSVToRGB(int $hue, float $saturation, float $value): array
{
if ($hue < 0 || $hue > 360 ||
$saturation < 0 || $saturation > 1 ||
$value < 0 || $value > 1) {
throw new InvalidArgumentException('Parameters exceed their intended ranges.');
}
self::validateParameters($hue, $saturation, $value);

$chroma = $value * $saturation;
$hueNormalized = $hue / 60;
$hMod2 = $hueNormalized - 2 * floor($hueNormalized / 2);
$secondMax = $chroma * (1 - abs($hMod2 - 1));

list($r, $g, $b) = self::calculateRGBRange($hueNormalized, $chroma, $secondMax);

return self::finalizeRGBCalculation($r, $g, $b, $value, $chroma);
}

private static function validateParameters(int $hue, float $saturation, float $value): void
{
if ($hue < 0 || $hue > 360 ||
$saturation < 0 || $saturation > 1 ||
$value < 0 || $value > 1) {
throw new InvalidArgumentException('Parameters exceed their intended ranges.');
}
}

private static function calculateRGBRange(float $hueNormalized, float $chroma, float $secondMax): array
{
if (0 <= $hueNormalized && $hueNormalized < 1) {
list($r, $g, $b) = array($chroma, $secondMax, 0);
return [$chroma, $secondMax, 0];
} elseif (1 <= $hueNormalized && $hueNormalized < 2) {
list($r, $g, $b) = array($secondMax, $chroma, 0);
return [$secondMax, $chroma, 0];
} elseif (2 <= $hueNormalized && $hueNormalized < 3) {
list($r, $g, $b) = array(0, $chroma, $secondMax);
return [0, $chroma, $secondMax];
} elseif (3 <= $hueNormalized && $hueNormalized < 4) {
list($r, $g, $b) = array(0, $secondMax, $chroma);
return [0, $secondMax, $chroma];
} elseif (4 <= $hueNormalized && $hueNormalized < 5) {
list($r, $g, $b) = array($secondMax, 0, $chroma);
} elseif (5 <= $hueNormalized && $hueNormalized < 6) {
list($r, $g, $b) = array($chroma, 0, $secondMax);
}
if (!isset($r) || !isset($g) || !isset($b)) {
throw new Exception('RGB calculation not possible. Check inputs!');
return [$secondMax, 0, $chroma];
} else {
return [$chroma, 0, $secondMax];
}
$m = $value - $chroma;
$r = intval(round(($r + $m) * 255));
$g = intval(round(($g + $m) * 255));
$b = intval(round(($b + $m) * 255));
}

return array($r, $g, $b);
private static function finalizeRGBCalculation(float $r, float $g, float $b, float $value, float $chroma): array
{
$m = $value - $chroma;
return array_map(fn($x) => intval(round(($x + $m) * 255)), [$r, $g, $b]);
}

/**
Expand All @@ -168,40 +211,6 @@ public static function RGBToHex(int $red, int $green, int $blue): string
return $hexr.$hexg.$hexb;
}

/**
* Calculate the components Chroma, Value, and Hue based on RGB color.
*
* @param int $red The red component of the RGB color (0-255).
* @param int $green The green component of the RGB color (0-255).
* @param int $blue The blue component of the RGB color (0-255).
* @return array An array containing the calculated values (maxRGB, minRGB, chroma, value, hue).
*/
public static function calculateCVH(int $red, int $green, int $blue): array
{
$normalizedRed = $red / 255;
$normalizedGreen = $green / 255;
$normalizedBlue = $blue / 255;

$maxRGB = max($normalizedRed, $normalizedGreen, $normalizedBlue);
$minRGB = min($normalizedRed, $normalizedGreen, $normalizedBlue);
$chroma = $maxRGB - $minRGB;
$value = $maxRGB; // also called brightness
if ($chroma == 0) {
$hue = 0;
} elseif ($maxRGB == $normalizedRed) {
$hue = 60 * (($normalizedGreen - $normalizedBlue) / $chroma);
} elseif ($maxRGB == $normalizedGreen) {
$hue = 60 * (2 + ($normalizedBlue - $normalizedRed) / $chroma);
} else {
$hue = 60 * (4 + ($normalizedRed - $normalizedGreen) / $chroma);
}

if ($hue < 0) {
$hue += 360;
}
return array($maxRGB, $minRGB, $chroma, $value, $hue);
}

/**
* Convert HSL color to RGB color space.
*
Expand All @@ -218,60 +227,19 @@ private static function HSLToRGB(int $hue, float $saturation, float $lightness):
$hMod2 = $hueNormalized - 2 * floor($hueNormalized / 2);
$intermediateValue = $chroma * (1 - abs($hMod2 - 1));

if (0 <= $hueNormalized && $hueNormalized < 1) {
list($r, $g, $b) = array($chroma, $intermediateValue, 0);
} elseif (1 <= $hueNormalized && $hueNormalized < 2) {
list($r, $g, $b) = array($intermediateValue, $chroma, 0);
} elseif (2 <= $hueNormalized && $hueNormalized < 3) {
list($r, $g, $b) = array(0, $chroma, $intermediateValue);
} elseif (3 <= $hueNormalized && $hueNormalized < 4) {
list($r, $g, $b) = array(0, $intermediateValue, $chroma);
} elseif (4 <= $hueNormalized && $hueNormalized < 5) {
list($r, $g, $b) = array($intermediateValue, 0, $chroma);
} elseif (5 <= $hueNormalized && $hueNormalized < 6) {
list($r, $g, $b) = array($chroma, 0, $intermediateValue);
}
if (!isset($r) || !isset($g) || !isset($b)) {
throw new Exception('RGB calculation not possible. Check inputs!');
}
$m = $lightness - $chroma / 2;
$r = intval(round(($r + $m) * 255));
$g = intval(round(($g + $m) * 255));
$b = intval(round(($b + $m) * 255));

return array($r, $g, $b);
}

/**
* Set the hexadecimal color value.
*
* @param string $color The hexadecimal color value.
* @return void
*/
public function setHex(string $color): void
{
if (!preg_match("/#[0-9a-fA-F]{3}/", $color) &&
!preg_match("/#[0-9a-fA-F]{6}/", $color)) {
return;
}
$color = substr($color, 1);
$this->hex = $color;
list($r, $g, $b) = self::calculateRGBRange($hueNormalized, $chroma, $intermediateValue);

$this->rgb = Color::HexToRGB($this->hex);
$this->hsl = Color::RGBToHSL($this->rgb[0], $this->rgb[1], $this->rgb[2]);
return self::finalizeRGBCalculation($r, $g, $b, $lightness, $chroma);
}

/**
* Set the RGB color.
* Get the HSL color values of the current object.
*
* @param array $color An array containing the RGB color values (red, green, blue).
* @return void
* @return array An array containing the HSL color values (hue, saturation, lightness).
*/
public function setRGB(array $color): void
public function getHSL(): array
{
$this->rgb = $color;
$this->hex = Color::RGBToHex($color[0], $color[1], $color[2]);
$this->hsl = Color::RGBToHSL($color[0], $color[1], $color[2]);
return $this->hsl;
}

/**
Expand All @@ -288,23 +256,26 @@ public function setHSL(array $color): void
}

/**
* Get the HSL color values of the current object.
* Get the RGB color values.
*
* @return array An array containing the HSL color values (hue, saturation, lightness).
* @return array An array containing the RGB color values (red, green, blue).
*/
public function getHSL(): array
public function getRGB(): array
{
return $this->hsl;
return $this->rgb;
}

/**
* Get the RGB color values.
* Set the RGB color.
*
* @return array An array containing the RGB color values (red, green, blue).
* @param array $color An array containing the RGB color values (red, green, blue).
* @return void
*/
public function getRGB(): array
public function setRGB(array $color): void
{
return $this->rgb;
$this->rgb = $color;
$this->hex = Color::RGBToHex($color[0], $color[1], $color[2]);
$this->hsl = Color::RGBToHSL($color[0], $color[1], $color[2]);
}

/**
Expand All @@ -317,6 +288,25 @@ public function getHex(): string
return '#'.$this->hex;
}

/**
* Set the hexadecimal color value.
*
* @param string $color The hexadecimal color value.
* @return void
*/
public function setHex(string $color): void
{
if (!preg_match("/#[0-9a-fA-F]{3}/", $color) &&
!preg_match("/#[0-9a-fA-F]{6}/", $color)) {
return;
}
$color = substr($color, 1);
$this->hex = $color;

$this->rgb = Color::HexToRGB($this->hex);
$this->hsl = Color::RGBToHSL($this->rgb[0], $this->rgb[1], $this->rgb[2]);
}

/**
* Get the color set based on the HSL values of the color.
*
Expand Down Expand Up @@ -350,19 +340,6 @@ public function brighten(int $amount = 10): void
$this->setHSL(array($hue, $saturation, $lightness));
}

/**
* Darken the color by reducing its lightness value.
*
* @param int $amount The amount by which to darken the color (0-100).
* @return void
*/
public function darken(int $amount = 10): void
{
list($hue, $saturation, $lightness) = $this->hsl;
$lightness = self::clamp($lightness - $amount / 100, 0, 1);
$this->setHSL(array($hue, $saturation, $lightness));
}

/**
* Clamp a number between a minimum and maximum value.
*
Expand All @@ -381,4 +358,17 @@ private static function clamp(int|float $num, int|float $min, int|float $max): i
return $num;
}

/**
* Darken the color by reducing its lightness value.
*
* @param int $amount The amount by which to darken the color (0-100).
* @return void
*/
public function darken(int $amount = 10): void
{
list($hue, $saturation, $lightness) = $this->hsl;
$lightness = self::clamp($lightness - $amount / 100, 0, 1);
$this->setHSL(array($hue, $saturation, $lightness));
}

}

0 comments on commit b7960ee

Please sign in to comment.