Файл: vendor/intervention/image/src/Colors/Oklab/Colorspace.php
Строк: 172
<?php
declare(strict_types=1);
namespace InterventionImageColorsOklab;
use InterventionImageColorsAbstractColorspace;
use InterventionImageColorsCmykColor as CmykColor;
use InterventionImageColorsHslColor as HslColor;
use InterventionImageColorsHsvColor as HsvColor;
use InterventionImageColorsOklabColor as OklabColor;
use InterventionImageColorsOklchColor as OklchColor;
use InterventionImageColorsRgbColor as RgbColor;
use InterventionImageColorsRgbColorspace as Rgb;
use InterventionImageColorsRgbNamedColor;
use InterventionImageExceptionsColorException;
use InterventionImageExceptionsInvalidArgumentException;
use InterventionImageInterfacesColorInterface;
use TypeError;
class Colorspace extends AbstractColorspace
{
/**
* Channel class names of colorspace.
*
* @var array<string>
*/
public static array $channels = [
ChannelsLightness::class,
ChannelsA::class,
ChannelsB::class,
ChannelsAlpha::class,
];
/**
* {@inheritdoc}
*
* @see ColorspaceInterface::colorFromNormalized()
*
* @throws InvalidArgumentException
*/
public static function colorFromNormalized(array $normalized): OklabColor
{
if (!in_array(count($normalized), [3, 4])) {
throw new InvalidArgumentException('Number of color channels must be 3 or 4 for ' . static::class);
}
// add alpha value if missing
$normalized = count($normalized) === 3 ? array_pad($normalized, 4, 1) : $normalized;
return new Color(...array_map(
function (string $channel, null|float $normalized) {
try {
return $channel::fromNormalized($normalized);
} catch (TypeError $e) {
throw new InvalidArgumentException(
'Normalized color value must be in range 0 to 1',
previous: $e,
);
}
},
self::$channels,
$normalized,
));
}
/**
* {@inheritdoc}
*
* @see ColorspaceInterface::importColor()
*
* @throws ColorException
*/
public function importColor(ColorInterface $color): OklabColor
{
return match ($color::class) {
CmykColor::class,
HsvColor::class,
NamedColor::class,
HslColor::class => $this->importViaRgbColor($color),
RgbColor::class => $this->importRgbColor($color),
OklchColor::class => $this->importOklchColor($color),
OklabColor::class => $color,
default => throw new ColorException(
'Unable to import color ' . $color::class . ' to ' . $this::class,
),
};
}
/**
* Import given RGB color OKLAB colorspace.
*
* @throws ColorException
*/
private function importRgbColor(RgbColor $color): OklabColor
{
$cbrt = fn(float $x): float => $x < 0 ? -abs($x) ** (1 / 3) : $x ** (1 / 3);
$rgbToLinear = fn(float $x): float => $x <= 0.04045 ? $x / 12.92 : (($x + 0.055) / 1.055) ** 2.4;
$r = $color->red()->normalized();
$g = $color->green()->normalized();
$b = $color->blue()->normalized();
$r = $rgbToLinear($r);
$g = $rgbToLinear($g);
$b = $rgbToLinear($b);
$l = 0.4122214708 * $r + 0.5363325363 * $g + 0.0514459929 * $b;
$m = 0.2119034982 * $r + 0.6806995451 * $g + 0.1073969566 * $b;
$s = 0.0883024619 * $r + 0.2817188376 * $g + 0.6299787005 * $b;
$l = $cbrt($l);
$m = $cbrt($m);
$s = $cbrt($s);
try {
return new Color(
0.2104542553 * $l + 0.7936177850 * $m - 0.0040720468 * $s,
1.9779984951 * $l - 2.4285922050 * $m + 0.4505937099 * $s,
0.0259040371 * $l + 0.7827717662 * $m - 0.8086757660 * $s,
$color->alpha()->normalized(),
);
} catch (InvalidArgumentException $e) {
throw new ColorException(
'Failed to import color ' . $color::class . ' to ' . $this::class,
previous: $e,
);
}
}
/**
* Import given OKLCH color OKLAB colorspace.
*
* @throws ColorException
*/
private function importOklchColor(OklchColor $color): OklabColor
{
$hRad = deg2rad($color->hue()->value());
try {
return new Color(
$color->lightness()->value(),
$color->chroma()->value() * cos($hRad),
$color->chroma()->value() * sin($hRad),
$color->alpha()->normalized(),
);
} catch (InvalidArgumentException $e) {
throw new ColorException(
'Failed to import color ' . $color::class . ' to ' . $this::class,
previous: $e,
);
}
}
/**
* Import given color to OKLAB color space by converting it to RGB first.
*
* @throws ColorException
*/
private function importViaRgbColor(NamedColor|CmykColor|HslColor|HsvColor $color): OklabColor
{
try {
$color = $color->toColorspace(Rgb::class)->toColorspace($this::class);
} catch (InvalidArgumentException $e) {
throw new ColorException(
'Failed to import color ' . $color::class . ' to ' . $this::class,
previous: $e,
);
}
if (!$color instanceof OklabColor) {
throw new ColorException('Failed to import color ' . $color::class . ' to ' . $this::class);
}
return $color;
}
}