1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-31 17:41:58 +02:00

Color Decoder

This commit is contained in:
Oliver Vogel
2021-10-31 07:46:01 +01:00
parent d4eaea5a9e
commit 4b7c182152
11 changed files with 137 additions and 26 deletions

View File

@@ -7,11 +7,11 @@ use Intervention\Image\Drivers\Gd\Color;
use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\DecoderInterface; use Intervention\Image\Interfaces\DecoderInterface;
use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Traits\CanValidateColorArray; use Intervention\Image\Traits\CanValidateColors;
class ArrayColorDecoder extends AbstractDecoder implements DecoderInterface class ArrayColorDecoder extends AbstractDecoder implements DecoderInterface
{ {
use CanValidateColorArray; use CanValidateColors;
public function decode($input): ImageInterface|ColorInterface public function decode($input): ImageInterface|ColorInterface
{ {
@@ -19,6 +19,10 @@ class ArrayColorDecoder extends AbstractDecoder implements DecoderInterface
$this->fail(); $this->fail();
} }
if (count($input) === 3) {
$input[] = 1;
}
list($r, $g, $b, $a) = $input; list($r, $g, $b, $a) = $input;
return new Color( return new Color(

View File

@@ -0,0 +1,27 @@
<?php
namespace Intervention\Image\Drivers\Gd\Decoders;
use Intervention\Image\Drivers\Gd\Color;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\DecoderInterface;
use Intervention\Image\Interfaces\ImageInterface;
class HexColorDecoder extends ArrayColorDecoder implements DecoderInterface
{
public function decode($input): ImageInterface|ColorInterface
{
$pattern = '/^#?([a-f0-9]{1,2})([a-f0-9]{1,2})([a-f0-9]{1,2})$/i';
$result = preg_match($pattern, $input, $matches);
if ($result !== 1) {
$this->fail();
}
return parent::decode([
strlen($matches[1]) == '1' ? hexdec($matches[1] . $matches[1]) : hexdec($matches[1]),
strlen($matches[2]) == '1' ? hexdec($matches[2] . $matches[2]) : hexdec($matches[2]),
strlen($matches[3]) == '1' ? hexdec($matches[3] . $matches[3]) : hexdec($matches[3]),
]);
}
}

View File

@@ -10,10 +10,12 @@ class InputHandler extends AbstractInputHandler
protected function chain(): AbstractDecoder protected function chain(): AbstractDecoder
{ {
return new Decoders\ArrayColorDecoder( return new Decoders\ArrayColorDecoder(
new Decoders\FilePathImageDecoder( new Decoders\HexColorDecoder(
new Decoders\BinaryImageDecoder( new Decoders\FilePathImageDecoder(
new Decoders\DataUriImageDecoder( new Decoders\BinaryImageDecoder(
new Decoders\Base64ImageDecoder() new Decoders\DataUriImageDecoder(
new Decoders\Base64ImageDecoder()
)
) )
) )
) )

View File

@@ -6,9 +6,12 @@ use Intervention\Image\Drivers\Gd\InputHandler;
use Intervention\Image\Interfaces\FrameInterface; use Intervention\Image\Interfaces\FrameInterface;
use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\ModifierInterface; use Intervention\Image\Interfaces\ModifierInterface;
use Intervention\Image\Traits\CanHandleInput;
class FillModifier implements ModifierInterface class FillModifier implements ModifierInterface
{ {
use CanHandleInput;
public function __construct($filling, ?int $x = null, ?int $y = null) public function __construct($filling, ?int $x = null, ?int $y = null)
{ {
$this->filling = $filling; $this->filling = $filling;
@@ -18,7 +21,7 @@ class FillModifier implements ModifierInterface
{ {
$width = $image->getWidth(); $width = $image->getWidth();
$height = $image->getHeight(); $height = $image->getHeight();
$filling = $this->getApplicableFilling(); $filling = $this->handleInput($this->filling);
foreach ($image as $frame) { foreach ($image as $frame) {
imagefilledrectangle($frame->getCore(), 0, 0, $width - 1, $height - 1, $filling); imagefilledrectangle($frame->getCore(), 0, 0, $width - 1, $height - 1, $filling);
@@ -26,9 +29,4 @@ class FillModifier implements ModifierInterface
return $image; return $image;
} }
protected function getApplicableFilling()
{
return (new InputHandler())->handle($this->filling);
}
} }

View File

@@ -8,11 +8,11 @@ use Intervention\Image\Drivers\Imagick\Color;
use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\DecoderInterface; use Intervention\Image\Interfaces\DecoderInterface;
use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Traits\CanValidateColorArray; use Intervention\Image\Traits\CanValidateColors;
class ArrayColorDecoder extends AbstractDecoder implements DecoderInterface class ArrayColorDecoder extends AbstractDecoder implements DecoderInterface
{ {
use CanValidateColorArray; use CanValidateColors;
public function decode($input): ImageInterface|ColorInterface public function decode($input): ImageInterface|ColorInterface
{ {

View File

@@ -0,0 +1,27 @@
<?php
namespace Intervention\Image\Drivers\Imagick\Decoders;
use Intervention\Image\Drivers\Imagick\Color;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\DecoderInterface;
use Intervention\Image\Interfaces\ImageInterface;
class HexColorDecoder extends ArrayColorDecoder implements DecoderInterface
{
public function decode($input): ImageInterface|ColorInterface
{
$pattern = '/^#?([a-f0-9]{1,2})([a-f0-9]{1,2})([a-f0-9]{1,2})$/i';
$result = preg_match($pattern, $input, $matches);
if ($result !== 1) {
$this->fail();
}
return parent::decode([
strlen($matches[1]) == '1' ? hexdec($matches[1] . $matches[1]) : hexdec($matches[1]),
strlen($matches[2]) == '1' ? hexdec($matches[2] . $matches[2]) : hexdec($matches[2]),
strlen($matches[3]) == '1' ? hexdec($matches[3] . $matches[3]) : hexdec($matches[3]),
]);
}
}

View File

@@ -10,10 +10,12 @@ class InputHandler extends AbstractInputHandler
protected function chain(): AbstractDecoder protected function chain(): AbstractDecoder
{ {
return new Decoders\ArrayColorDecoder( return new Decoders\ArrayColorDecoder(
new Decoders\FilePathImageDecoder( new Decoders\HexColorDecoder(
new Decoders\BinaryImageDecoder( new Decoders\FilePathImageDecoder(
new Decoders\DataUriImageDecoder( new Decoders\BinaryImageDecoder(
new Decoders\Base64ImageDecoder() new Decoders\DataUriImageDecoder(
new Decoders\Base64ImageDecoder()
)
) )
) )
) )

View File

@@ -6,9 +6,12 @@ use ImagickDraw;
use Intervention\Image\Drivers\Imagick\InputHandler; use Intervention\Image\Drivers\Imagick\InputHandler;
use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\ModifierInterface; use Intervention\Image\Interfaces\ModifierInterface;
use Intervention\Image\Traits\CanHandleInput;
class FillModifier implements ModifierInterface class FillModifier implements ModifierInterface
{ {
use CanHandleInput;
public function __construct($filling, ?int $x = null, ?int $y = null) public function __construct($filling, ?int $x = null, ?int $y = null)
{ {
$this->filling = $filling; $this->filling = $filling;
@@ -16,8 +19,10 @@ class FillModifier implements ModifierInterface
public function apply(ImageInterface $image): ImageInterface public function apply(ImageInterface $image): ImageInterface
{ {
$filling = $this->handleInput($this->filling);
$draw = new ImagickDraw(); $draw = new ImagickDraw();
$draw->setFillColor($this->getApplicableFilling()->getPixel()); $draw->setFillColor($filling->getPixel());
$draw->rectangle(0, 0, $image->getWidth(), $image->getHeight()); $draw->rectangle(0, 0, $image->getWidth(), $image->getHeight());
foreach ($image as $frame) { foreach ($image as $frame) {
@@ -26,9 +31,4 @@ class FillModifier implements ModifierInterface
return $image; return $image;
} }
protected function getApplicableFilling()
{
return (new InputHandler())->handle($this->filling);
}
} }

View File

@@ -0,0 +1,11 @@
<?php
namespace Intervention\Image\Traits;
trait CanHandleInput
{
protected function handleInput($value)
{
return (new InputHandler())->handle($value);
}
}

View File

@@ -2,7 +2,7 @@
namespace Intervention\Image\Traits; namespace Intervention\Image\Traits;
trait CanValidateColorArray trait CanValidateColors
{ {
protected function isValidColorArray($input): bool protected function isValidColorArray($input): bool
{ {
@@ -22,7 +22,7 @@ trait CanValidateColorArray
} }
// validate alpha value // validate alpha value
if ($input[3] > 1 || $input[3] < 0) { if (isset($input[3]) && ($input[3] > 1 || $input[3] < 0)) {
return false; return false;
} }

View File

@@ -58,5 +58,45 @@ class InputHandlerTest extends TestCase
$input = [181, 55, 23, .5]; $input = [181, 55, 23, .5];
$result = $handler->handle($input); $result = $handler->handle($input);
$this->assertInstanceOf(Color::class, $result); $this->assertInstanceOf(Color::class, $result);
$handler = new InputHandler();
$input = [181, 55, 23];
$result = $handler->handle($input);
$this->assertInstanceOf(Color::class, $result);
}
public function testHandleHexColor(): void
{
$handler = new InputHandler();
$input = 'ccff33';
$result = $handler->handle($input);
$this->assertInstanceOf(Color::class, $result);
$this->assertEquals(204, $result->red());
$this->assertEquals(255, $result->green());
$this->assertEquals(51, $result->blue());
$handler = new InputHandler();
$input = 'cf3';
$result = $handler->handle($input);
$this->assertInstanceOf(Color::class, $result);
$this->assertEquals(204, $result->red());
$this->assertEquals(255, $result->green());
$this->assertEquals(51, $result->blue());
$handler = new InputHandler();
$input = '#123456';
$result = $handler->handle($input);
$this->assertInstanceOf(Color::class, $result);
$this->assertEquals(18, $result->red());
$this->assertEquals(52, $result->green());
$this->assertEquals(86, $result->blue());
$handler = new InputHandler();
$input = '#333';
$result = $handler->handle($input);
$this->assertInstanceOf(Color::class, $result);
$this->assertEquals(51, $result->red());
$this->assertEquals(51, $result->green());
$this->assertEquals(51, $result->blue());
} }
} }