Skip to content

Commit

Permalink
Add static color factory method
Browse files Browse the repository at this point in the history
  • Loading branch information
olivervogel committed Oct 21, 2023
1 parent a1f7548 commit 3401fef
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 0 deletions.
85 changes: 85 additions & 0 deletions src/Colors/Rgb/Color.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 = [
Expand All @@ -27,33 +40,80 @@ 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) {
return $channel->value();
}, $this->channels());
}

/**
* {@inheritdoc}
*
* @see ColorInterface::toHex()
*/
public function toHex(string $prefix = ''): string
{
if ($this->isFullyOpaque()) {
Expand All @@ -76,6 +136,11 @@ public function toHex(string $prefix = ''): string
);
}

/**
* {@inheritdoc}
*
* @see ColorInterface::convertTo()
*/
public function convertTo(string|ColorspaceInterface $colorspace): ColorInterface
{
$colorspace = match (true) {
Expand All @@ -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()) {
Expand All @@ -111,13 +186,23 @@ public function toString(): string
);
}

/**
* {@inheritdoc}
*
* @see ColorInterface::isGreyscale()
*/
public function isGreyscale(): bool
{
$values = [$this->red()->value(), $this->green()->value(), $this->blue()->value()];

return count(array_unique($values, SORT_REGULAR)) === 1;
}

/**
* {@inheritdoc}
*
* @see ColorInterface::__toString()
*/
public function __toString(): string
{
return $this->toString();
Expand Down
10 changes: 10 additions & 0 deletions src/Drivers/Abstract/AbstractInputHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
57 changes: 57 additions & 0 deletions src/Interfaces/ColorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
11 changes: 11 additions & 0 deletions tests/Colors/Rgb/ColorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 3401fef

Please sign in to comment.