diff --git a/src/Colors/Rgb/Color.php b/src/Colors/Rgb/Color.php index c05aaf5f1..d71175659 100644 --- a/src/Colors/Rgb/Color.php +++ b/src/Colors/Rgb/Color.php @@ -7,6 +7,7 @@ use Intervention\Image\Colors\Rgb\Channels\Red; use Intervention\Image\Colors\Rgb\Channels\Alpha; use Intervention\Image\Colors\Traits\CanHandleChannels; +use Intervention\Image\Drivers\Abstract\AbstractInputHandler; use Intervention\Image\Interfaces\ColorChannelInterface; use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\ColorspaceInterface; @@ -15,8 +16,20 @@ class Color implements ColorInterface { use CanHandleChannels; + /** + * Color channels + */ protected array $channels; + /** + * Create new instance + * + * @param int $r + * @param int $g + * @param int $b + * @param int $a + * @return ColorInterface + */ public function __construct(int $r, int $g, int $b, int $a = 255) { $this->channels = [ @@ -27,26 +40,68 @@ public function __construct(int $r, int $g, int $b, int $a = 255) ]; } + /** + * {@inheritdoc} + * + * @see ColorInterface::create() + */ + public static function create(mixed $input): ColorInterface + { + return (new class ([ + Decoders\HexColorDecoder::class, + Decoders\StringColorDecoder::class, + Decoders\TransparentColorDecoder::class, + Decoders\HtmlColornameDecoder::class, + ]) extends AbstractInputHandler + { + })->handle($input); + } + + /** + * Return the RGB red color channel + * + * @return ColorChannelInterface + */ public function red(): ColorChannelInterface { return $this->channel(Red::class); } + /** + * Return the RGB green color channel + * + * @return ColorChannelInterface + */ public function green(): ColorChannelInterface { return $this->channel(Green::class); } + /** + * Return the RGB blue color channel + * + * @return ColorChannelInterface + */ public function blue(): ColorChannelInterface { return $this->channel(Blue::class); } + /** + * Return the colors alpha channel + * + * @return ColorChannelInterface + */ public function alpha(): ColorChannelInterface { return $this->channel(Alpha::class); } + /** + * {@inheritdoc} + * + * @see ColorInterface::toArray() + */ public function toArray(): array { return array_map(function (ColorChannelInterface $channel) { @@ -54,6 +109,11 @@ public function toArray(): array }, $this->channels()); } + /** + * {@inheritdoc} + * + * @see ColorInterface::toHex() + */ public function toHex(string $prefix = ''): string { if ($this->isFullyOpaque()) { @@ -76,6 +136,11 @@ public function toHex(string $prefix = ''): string ); } + /** + * {@inheritdoc} + * + * @see ColorInterface::convertTo() + */ public function convertTo(string|ColorspaceInterface $colorspace): ColorInterface { $colorspace = match (true) { @@ -86,11 +151,21 @@ public function convertTo(string|ColorspaceInterface $colorspace): ColorInterfac return $colorspace->convertColor($this); } + /** + * Determine if the current color is fully opaque + * + * @return bool + */ public function isFullyOpaque(): bool { return $this->alpha()->value() === 255; } + /** + * {@inheritdoc} + * + * @see ColorInterface::toString() + */ public function toString(): string { if ($this->isFullyOpaque()) { @@ -111,6 +186,11 @@ public function toString(): string ); } + /** + * {@inheritdoc} + * + * @see ColorInterface::isGreyscale() + */ public function isGreyscale(): bool { $values = [$this->red()->value(), $this->green()->value(), $this->blue()->value()]; @@ -118,6 +198,11 @@ public function isGreyscale(): bool return count(array_unique($values, SORT_REGULAR)) === 1; } + /** + * {@inheritdoc} + * + * @see ColorInterface::__toString() + */ public function __toString(): string { return $this->toString(); diff --git a/src/Drivers/Abstract/AbstractInputHandler.php b/src/Drivers/Abstract/AbstractInputHandler.php index 92ac0b234..faf90ad50 100644 --- a/src/Drivers/Abstract/AbstractInputHandler.php +++ b/src/Drivers/Abstract/AbstractInputHandler.php @@ -14,6 +14,16 @@ abstract class AbstractInputHandler */ protected array $decoders = []; + /** + * Create new instance + * + * @param array $decoders + */ + public function __construct(array $decoders = []) + { + $this->decoders = count($decoders) ? $decoders : $this->decoders; + } + /** * Stack the decoder array into a nested decoder object * diff --git a/src/Interfaces/ColorInterface.php b/src/Interfaces/ColorInterface.php index 1594b8574..5d40eef25 100644 --- a/src/Interfaces/ColorInterface.php +++ b/src/Interfaces/ColorInterface.php @@ -4,12 +4,69 @@ interface ColorInterface { + /** + * Static color factory method that passed input to color decoding input handler + * + * @param mixed $input + * @return ColorInterface + * @throws \Intervention\Image\Exceptions\DecoderException + */ + public static function create(mixed $input): ColorInterface; + + /** + * Cast color object to string + * + * @return string + */ public function __toString(): string; + + /** + * Cast color object to string + * + * @return string + */ public function toString(): string; + + /** + * Cast color object to array + * + * @return array + */ public function toArray(): array; + + /** + * Cast color object to hex encoded web color + * + * @return string + */ public function toHex(): string; + + /** + * Return array of all color channels + * + * @return array + */ public function channels(): array; + + /** + * Retrieve the color channel by its classname + * + * @param string $classname + * @return ColorChannelInterface + */ public function channel(string $classname): ColorChannelInterface; + + /** + * Convert color to given colorspace + * + * @return ColorInterface + */ public function convertTo(string|ColorspaceInterface $colorspace): ColorInterface; + + /** + * Determine if the current color is gray + * + * @return bool + */ public function isGreyscale(): bool; } diff --git a/tests/Colors/Rgb/ColorTest.php b/tests/Colors/Rgb/ColorTest.php index bcbbe53ab..b4020c3c2 100644 --- a/tests/Colors/Rgb/ColorTest.php +++ b/tests/Colors/Rgb/ColorTest.php @@ -23,6 +23,17 @@ public function testConstructor(): void $this->assertInstanceOf(Color::class, $color); } + public function testCreate(): void + { + $color = Color::create('ccc'); + $this->assertInstanceOf(Color::class, $color); + $this->assertEquals([204, 204, 204, 255], $color->toArray()); + + $color = Color::create('rgba(10, 20, 30, .2)'); + $this->assertInstanceOf(Color::class, $color); + $this->assertEquals([10, 20, 30, 51], $color->toArray()); + } + public function testChannels(): void { $color = new Color(10, 20, 30);