Файл: vendor/intervention/image/src/Colors/AbstractColor.php
Строк: 336
<?php
declare(strict_types=1);
namespace InterventionImageColors;
use InterventionImageColorsHslChannelsLuminance;
use InterventionImageColorsHslChannelsSaturation;
use InterventionImageColorsHslColorspace as HslColorspace;
use InterventionImageColorsRgbChannelsBlue;
use InterventionImageColorsRgbChannelsGreen;
use InterventionImageColorsRgbChannelsRed;
use InterventionImageColorsRgbColorspace as RgbColorspace;
use InterventionImageExceptionsColorException;
use InterventionImageExceptionsInvalidArgumentException;
use InterventionImageInterfacesColorChannelInterface;
use InterventionImageInterfacesColorInterface;
use InterventionImageInterfacesColorspaceInterface;
use ReflectionClass;
use Stringable;
abstract class AbstractColor implements ColorInterface, Stringable
{
/**
* Color channels.
*
* @var array<ColorChannelInterface>
*/
protected array $channels;
/**
* {@inheritdoc}
*
* @see ColorInterface::channels()
*/
public function channels(): array
{
return $this->channels;
}
/**
* {@inheritdoc}
*
* @see ColorInterface::channel()
*
* @throws InvalidArgumentException
*/
public function channel(string $classname): ColorChannelInterface
{
$channels = array_filter(
$this->channels(),
fn(ColorChannelInterface $channel): bool => $channel::class === $classname,
);
if (count($channels) === 0) {
throw new InvalidArgumentException('Color channel ' . $classname . ' could not be found');
}
return reset($channels);
}
/**
* {@inheritdoc}
*
* @see ColorInterface::toColorspace()
*
* @throws InvalidArgumentException
*/
public function toColorspace(string|ColorspaceInterface $colorspace): ColorInterface
{
if (is_string($colorspace) && !class_exists($colorspace)) {
throw new InvalidArgumentException('Unknown color space (' . $colorspace . ') as conversion target');
}
$colorspace = is_string($colorspace) ? new $colorspace() : $colorspace;
if (!$colorspace instanceof ColorspaceInterface) {
throw new InvalidArgumentException('Given color space must implement ' . ColorspaceInterface::class);
}
return $colorspace->importColor($this);
}
/**
* {@inheritdoc}
*
* @see ColorInterface::isTransparent()
*/
public function isTransparent(): bool
{
return $this->alpha()->value() < $this->alpha()->max();
}
/**
* {@inheritdoc}
*
* @see ColorInterface::isClear()
*/
public function isClear(): bool
{
return floatval($this->alpha()->value()) === 0.0;
}
/**
* {@inheritdoc}
*
* @see ColorInterface::withTransparency()
*
* @throws InvalidArgumentException
*/
public function withTransparency(float $transparency): ColorInterface
{
$color = clone $this;
$color->channels = array_map(
fn(ColorChannelInterface $channel): ColorChannelInterface =>
$channel instanceof AlphaChannel ? $channel::fromNormalized($transparency) : $channel,
$this->channels,
);
return $color;
}
/**
* {@inheritdoc}
*
* @see ColorInterface::withBrightness()
*
* @throws InvalidArgumentException
*/
public function withBrightness(int $level): ColorInterface
{
$hsl = clone $this->toColorspace(HslColorspace::class);
$hsl->channel(Luminance::class)->scale($level);
return $hsl->toColorspace($this->colorspace());
}
/**
* {@inheritdoc}
*
* @see ColorInterface::withSaturation()
*
* @throws InvalidArgumentException
*/
public function withSaturation(int $level): ColorInterface
{
$hsl = clone $this->toColorspace(HslColorspace::class);
$hsl->channel(Saturation::class)->scale($level);
return $hsl->toColorspace($this->colorspace());
}
/**
* {@inheritdoc}
*
* @see ColorInterface::withInversion()
*
* @throws ColorException
*/
public function withInversion(): ColorInterface
{
try {
$rgb = $this->toColorspace(RgbColorspace::class);
} catch (InvalidArgumentException) {
throw new ColorException('Failed to invert color');
}
try {
$inverted = new InterventionImageColorsRgbColor(
255 - $rgb->channel(Red::class)->value(),
255 - $rgb->channel(Green::class)->value(),
255 - $rgb->channel(Blue::class)->value(),
$rgb->alpha()->normalized(),
);
return $inverted->toColorspace($this->colorspace());
} catch (InvalidArgumentException) {
throw new ColorException('Failed to invert color');
}
}
/**
* Show debug info for the current color.
*
* @return array<string, string>
*/
public function __debugInfo(): array
{
return array_reduce($this->channels(), function (array $result, ColorChannelInterface $item) {
$key = strtolower((new ReflectionClass($item))->getShortName());
$result[$key] = $item->toString();
return $result;
}, []);
}
/**
* Clone color.
*/
public function __clone(): void
{
foreach ($this->channels as $key => $channel) {
$this->channels[$key] = clone $channel;
}
}
/**
* {@inheritdoc}
*
* @see ColorInterface::__toString()
*/
public function __toString(): string
{
return $this->toString();
}
}