*/ public static array $channels = [ Channels\Hue::class, Channels\Saturation::class, Channels\Luminance::class ]; /** * {@inheritdoc} * * @see ColorspaceInterface::colorFromNormalized() */ public function colorFromNormalized(array $normalized): ColorInterface { $values = array_map(function ($classname, $value_normalized) { return (new $classname(normalized: $value_normalized))->value(); }, self::$channels, $normalized); return new Color(...$values); } /** * @param ColorInterface $color * @return ColorInterface * @throws ColorException */ public function importColor(ColorInterface $color): ColorInterface { return match ($color::class) { CmykColor::class => $this->importRgbColor($color->convertTo(RgbColorspace::class)), RgbColor::class => $this->importRgbColor($color), HsvColor::class => $this->importHsvColor($color), default => $color, }; } /** * @param ColorInterface $color * @return ColorInterface * @throws ColorException */ protected function importRgbColor(ColorInterface $color): ColorInterface { if (!($color instanceof RgbColor)) { throw new ColorException('Unabled to import color of type ' . $color::class . '.'); } // normalized values of rgb channels $values = array_map(function ($channel) { return $channel->normalize(); }, $color->channels()); // take only RGB $values = array_slice($values, 0, 3); // calculate Luminance $min = min(...$values); $max = max(...$values); $luminance = ($max + $min) / 2; $delta = $max - $min; // calculate saturation $saturation = match (true) { $delta == 0 => 0, default => $delta / (1 - abs(2 * $luminance - 1)), }; // calculate hue list($r, $g, $b) = $values; $hue = match (true) { ($delta == 0) => 0, ($max == $r) => 60 * fmod((($g - $b) / $delta), 6), ($max == $g) => 60 * ((($b - $r) / $delta) + 2), ($max == $b) => 60 * ((($r - $g) / $delta) + 4), default => 0, }; $hue = ($hue + 360) % 360; // normalize hue return new Color( intval(round($hue)), intval(round($saturation * 100)), intval(round($luminance * 100)), ); } /** * @param ColorInterface $color * @return ColorInterface * @throws ColorException */ protected function importHsvColor(ColorInterface $color): ColorInterface { if (!($color instanceof HsvColor)) { throw new ColorException('Unabled to import color of type ' . $color::class . '.'); } // normalized values of hsv channels list($h, $s, $v) = array_map(function ($channel) { return $channel->normalize(); }, $color->channels()); // calculate Luminance $luminance = (2 - $s) * $v / 2; // calculate Saturation $saturation = match (true) { $luminance == 0 => $s, $luminance == 1 => 0, $luminance < .5 => $s * $v / ($luminance * 2), default => $s * $v / (2 - $luminance * 2), }; return new Color( intval(round($h * 360)), intval(round($saturation * 100)), intval(round($luminance * 100)), ); } }