mirror of
https://github.com/Intervention/image.git
synced 2025-08-28 16:19:50 +02:00
Replace color implementation in FillModifiers
This commit is contained in:
@@ -4,7 +4,7 @@ services:
|
||||
tests:
|
||||
build: ./
|
||||
working_dir: /project
|
||||
command: bash -c "composer install && ./vendor/bin/phpunit -vvv --filter=InputHandlerTest"
|
||||
command: bash -c "composer install && ./vendor/bin/phpunit -vvv"
|
||||
volumes:
|
||||
- ./:/project
|
||||
analysis:
|
||||
|
@@ -42,4 +42,14 @@ class Cyan implements ColorChannelInterface
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function toString(): string
|
||||
{
|
||||
return (string) $this->value();
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
|
@@ -91,7 +91,7 @@ class Color implements ColorInterface
|
||||
return $this->convertTo(CmykColorspace::class);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
public function toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'cmyk(%d, %d, %d, %d)',
|
||||
@@ -101,4 +101,9 @@ class Color implements ColorInterface
|
||||
$this->key()->value()
|
||||
);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
|
34
src/Colors/Cmyk/Parser.php
Normal file
34
src/Colors/Cmyk/Parser.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk;
|
||||
|
||||
use Intervention\Image\Exceptions\ColorException;
|
||||
|
||||
class Parser
|
||||
{
|
||||
public static function parse(mixed $value): Color
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
throw new ColorException('Unable to parse color');
|
||||
}
|
||||
|
||||
return static::fromString($value);
|
||||
}
|
||||
|
||||
public static function fromString(string $input): Color
|
||||
{
|
||||
// cmyk(100%, 100%, 100%, 100%)
|
||||
$pattern = '/^cmyk\((?P<c>[0-9\.]+)%?, ?(?P<m>[0-9\.]+)%?, ?(?P<y>[0-9\.]+)%?, ?(?P<k>[0-9\.]+)%?\)$/';
|
||||
$result = preg_match($pattern, $input, $matches);
|
||||
if ($result === 1) {
|
||||
return new Color(
|
||||
intval(round(floatval($matches['c']))),
|
||||
intval(round(floatval($matches['m']))),
|
||||
intval(round(floatval($matches['y']))),
|
||||
intval(round(floatval($matches['k'])))
|
||||
);
|
||||
}
|
||||
|
||||
throw new ColorException('Unable to parse color');
|
||||
}
|
||||
}
|
28
src/Colors/Parser.php
Normal file
28
src/Colors/Parser.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Colors;
|
||||
|
||||
use Intervention\Image\Exceptions\ColorException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
|
||||
class Parser
|
||||
{
|
||||
protected static $parsers = [
|
||||
Rgb\Parser::class,
|
||||
Rgba\Parser::class,
|
||||
Cmyk\Parser::class,
|
||||
];
|
||||
|
||||
public static function parse(mixed $value): ColorInterface
|
||||
{
|
||||
foreach (static::$parsers as $parser) {
|
||||
try {
|
||||
return forward_static_call([$parser, 'parse'], $value);
|
||||
} catch (ColorException $e) {
|
||||
# move on...
|
||||
}
|
||||
}
|
||||
|
||||
throw new ColorException('Unable to parse color');
|
||||
}
|
||||
}
|
@@ -42,4 +42,14 @@ class Red implements ColorChannelInterface
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function toString(): string
|
||||
{
|
||||
return (string) $this->value();
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
|
@@ -87,7 +87,7 @@ class Color implements ColorInterface
|
||||
return $this->convertTo(RgbaColorspace::class);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
public function toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'rgb(%d, %d, %d)',
|
||||
@@ -96,4 +96,9 @@ class Color implements ColorInterface
|
||||
$this->blue()->value()
|
||||
);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
|
@@ -6,6 +6,33 @@ use Intervention\Image\Exceptions\ColorException;
|
||||
|
||||
class Parser
|
||||
{
|
||||
public static function parse(mixed $value): Color
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
throw new ColorException('Unable to parse color');
|
||||
}
|
||||
|
||||
try {
|
||||
return static::fromHex($value);
|
||||
} catch (ColorException $e) {
|
||||
# move on
|
||||
}
|
||||
|
||||
try {
|
||||
return static::fromString($value);
|
||||
} catch (ColorException $e) {
|
||||
# move on
|
||||
}
|
||||
|
||||
try {
|
||||
return static::fromName($value);
|
||||
} catch (ColorException $e) {
|
||||
# move on
|
||||
}
|
||||
|
||||
throw new ColorException('Unable to parse color');
|
||||
}
|
||||
|
||||
public static function fromHex(string $input): Color
|
||||
{
|
||||
$pattern = '/^#?(?P<hex>[0-9a-f]{3}|[0-9a-f]{6})$/i';
|
||||
@@ -30,14 +57,29 @@ class Parser
|
||||
|
||||
public static function fromString(string $input): Color
|
||||
{
|
||||
$pattern = '/^rgb\((?P<r>[0-9]{1,3}), ?(?P<g>[0-9]{1,3}), ?(?P<b>[0-9]{1,3})\)$/';
|
||||
// rgb(255, 255, 255)
|
||||
$pattern = '/^s?rgb\((?P<r>[0-9]{1,3}), ?(?P<g>[0-9]{1,3}), ?(?P<b>[0-9]{1,3})\)$/';
|
||||
$result = preg_match($pattern, $input, $matches);
|
||||
|
||||
if ($result !== 1) {
|
||||
throw new ColorException('Unable to parse color');
|
||||
if ($result === 1) {
|
||||
return new Color(
|
||||
$matches['r'],
|
||||
$matches['g'],
|
||||
$matches['b']
|
||||
);
|
||||
}
|
||||
|
||||
return new Color($matches['r'], $matches['g'], $matches['b']);
|
||||
// rgb(100%, 100%, 100%)
|
||||
$pattern = '/^s?rgb\((?P<r>[0-9\.]+)%, ?(?P<g>[0-9\.]+)%, ?(?P<b>[0-9\.]+)%\)$/';
|
||||
$result = preg_match($pattern, $input, $matches);
|
||||
if ($result === 1) {
|
||||
return new Color(
|
||||
intval(round(floatval($matches['r']) / 100 * 255)),
|
||||
intval(round(floatval($matches['g']) / 100 * 255)),
|
||||
intval(round(floatval($matches['b']) / 100 * 255))
|
||||
);
|
||||
}
|
||||
|
||||
throw new ColorException('Unable to parse color');
|
||||
}
|
||||
|
||||
public static function fromName(string $input): Color
|
||||
|
@@ -4,5 +4,13 @@ namespace Intervention\Image\Colors\Rgba\Channels;
|
||||
|
||||
class Alpha extends Red
|
||||
{
|
||||
//
|
||||
public function toString(): string
|
||||
{
|
||||
return strval(round($this->normalize(), 6));
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
|
@@ -81,7 +81,7 @@ class Color extends RgbColor
|
||||
return $this->convertTo(CmykColorspace::class);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
public function toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'rgba(%d, %d, %d, %.1F)',
|
||||
@@ -91,4 +91,9 @@ class Color extends RgbColor
|
||||
$this->alpha()->normalize(),
|
||||
);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
|
@@ -38,18 +38,31 @@ class Parser extends RgbParser
|
||||
|
||||
public static function fromString(string $input): Color
|
||||
{
|
||||
$pattern = '/^rgba\((?P<r>[0-9]{1,3}), *(?P<g>[0-9]{1,3}), *(?P<b>[0-9]{1,3}), *(?P<a>((1|0))?(\.[0-9]+)?)\)$/';
|
||||
// rgba(255, 255, 255, 1.0)
|
||||
$pattern = '/^s?rgba\((?P<r>[0-9]{1,3}), *(?P<g>[0-9]{1,3}), *(?P<b>[0-9]{1,3}), *(?P<a>((1|0))?(\.[0-9]+)?)\)$/';
|
||||
$result = preg_match($pattern, $input, $matches);
|
||||
|
||||
if ($result !== 1) {
|
||||
throw new ColorException('Unable to parse color');
|
||||
if ($result === 1) {
|
||||
return new Color(
|
||||
$matches['r'],
|
||||
$matches['g'],
|
||||
$matches['b'],
|
||||
intval(round(floatval($matches['a']) * 255))
|
||||
);
|
||||
}
|
||||
|
||||
return new Color(
|
||||
$matches['r'],
|
||||
$matches['g'],
|
||||
$matches['b'],
|
||||
intval(round(floatval($matches['a']) * 255))
|
||||
);
|
||||
// rgba(100%, 100%, 100%, 100%)
|
||||
$pattern = '/s?rgba\((?P<r>[0-9\.]+)%, ?(?P<g>[0-9\.]+)%, ?(?P<b>[0-9\.]+)%, ?(?P<a>[0-9\.]+)%\)/';
|
||||
$result = preg_match($pattern, $input, $matches);
|
||||
if ($result === 1) {
|
||||
return new Color(
|
||||
intval(round(floatval($matches['r']) / 100 * 255)),
|
||||
intval(round(floatval($matches['g']) / 100 * 255)),
|
||||
intval(round(floatval($matches['b']) / 100 * 255)),
|
||||
intval(round(floatval($matches['a']) / 100 * 255))
|
||||
);
|
||||
}
|
||||
|
||||
throw new ColorException('Unable to parse color');
|
||||
}
|
||||
}
|
||||
|
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\AbstractColor;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
|
||||
class Color extends AbstractColor implements ColorInterface
|
||||
{
|
||||
public function __construct(protected int $value = 0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function red(): int
|
||||
{
|
||||
return $this->toArray()[0];
|
||||
}
|
||||
|
||||
public function green(): int
|
||||
{
|
||||
return $this->toArray()[1];
|
||||
}
|
||||
|
||||
public function blue(): int
|
||||
{
|
||||
return $this->toArray()[2];
|
||||
}
|
||||
|
||||
public function alpha(): float
|
||||
{
|
||||
return $this->toArray()[3];
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
$a = ($this->value >> 24) & 0x7F;
|
||||
$r = ($this->value >> 16) & 0xFF;
|
||||
$g = ($this->value >> 8) & 0xFF;
|
||||
$b = $this->value & 0xFF;
|
||||
$a = (float) round(1 - $a / 127, 2);
|
||||
|
||||
return [$r, $g, $b, $a];
|
||||
}
|
||||
|
||||
public function toInt(): int
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
61
src/Drivers/Gd/ColorTransformer.php
Normal file
61
src/Drivers/Gd/ColorTransformer.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd;
|
||||
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Colors\Rgba\Color;
|
||||
|
||||
class ColorTransformer
|
||||
{
|
||||
/**
|
||||
* Transforms GD Library integer color value to RGBA color object
|
||||
*
|
||||
* @param int $value
|
||||
* @return Color
|
||||
*/
|
||||
public static function colorFromInteger(int $value): Color
|
||||
{
|
||||
$a = ($value >> 24) & 0xFF;
|
||||
$r = ($value >> 16) & 0xFF;
|
||||
$g = ($value >> 8) & 0xFF;
|
||||
$b = $value & 0xFF;
|
||||
|
||||
// convert gd apha integer to intervention alpha integer
|
||||
// ([opaque]0-127[transparent]) to ([opaque]255-0[transparent])
|
||||
$a = (int) static::convertRange($a, 127, 0, 0, 255);
|
||||
|
||||
return new Color($r, $g, $b, $a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms given color to the corresponding GD Library integer value
|
||||
*
|
||||
* @param ColorInterface $color
|
||||
* @return int
|
||||
*/
|
||||
public static function colorToInteger(ColorInterface $color): int
|
||||
{
|
||||
$color = $color->toRgba();
|
||||
|
||||
$r = $color->red()->value();
|
||||
$g = $color->green()->value();
|
||||
$b = $color->blue()->value();
|
||||
$a = $color->alpha()->value();
|
||||
|
||||
// convert alpha value to gd alpha
|
||||
// ([opaque]255-0[transparent]) to ([opaque]0-127[transparent])
|
||||
$a = (int) static::convertRange($a, 0, 255, 127, 0);
|
||||
|
||||
return ($a << 24) + ($r << 16) + ($g << 8) + $b;
|
||||
}
|
||||
|
||||
private static function convertRange(
|
||||
float|int $input,
|
||||
float|int $min,
|
||||
float|int $max,
|
||||
float|int $targetMin,
|
||||
float|int $targetMax
|
||||
): float|int {
|
||||
return ceil(((($input - $min) * ($targetMax - $targetMin)) / ($max - $min)) + $targetMin);
|
||||
}
|
||||
}
|
@@ -2,19 +2,20 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class TransparentColorDecoder extends RgbArrayColorDecoder implements DecoderInterface
|
||||
class ColorObjectDecoder extends AbstractDecoder implements DecoderInterface
|
||||
{
|
||||
public function decode($input): ImageInterface|ColorInterface
|
||||
{
|
||||
if (! is_string($input) || strtolower($input) !== 'transparent') {
|
||||
if (! is_a($input, ColorInterface::class)) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
return parent::decode([0, 0, 0, 0]);
|
||||
return $input;
|
||||
}
|
||||
}
|
@@ -69,7 +69,7 @@ class Image extends AbstractImage implements ImageInterface, IteratorAggregate
|
||||
public function pickColor(int $x, int $y, int $frame_key = 0): ?ColorInterface
|
||||
{
|
||||
if ($frame = $this->getFrame($frame_key)) {
|
||||
return new Color(imagecolorat($frame->getCore(), $x, $y));
|
||||
return ColorTransformer::colorFromInteger(imagecolorat($frame->getCore(), $x, $y));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@@ -8,6 +8,7 @@ class InputHandler extends AbstractInputHandler
|
||||
{
|
||||
protected $decoders = [
|
||||
Decoders\ImageObjectDecoder::class,
|
||||
Decoders\ColorObjectDecoder::class,
|
||||
Decoders\FilePointerImageDecoder::class,
|
||||
Decoders\HtmlColorNameDecoder::class,
|
||||
Decoders\HexColorDecoder::class,
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Modifiers;
|
||||
|
||||
use Intervention\Image\Drivers\Gd\ColorTransformer;
|
||||
use Intervention\Image\Drivers\Gd\Frame;
|
||||
use Intervention\Image\Geometry\Point;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
@@ -10,9 +11,11 @@ use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class FillModifier implements ModifierInterface
|
||||
{
|
||||
protected $gd_color;
|
||||
|
||||
public function __construct(protected ColorInterface $color, protected ?Point $position = null)
|
||||
{
|
||||
//
|
||||
$this->gd_color = ColorTransformer::colorToInteger($color);
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
@@ -34,7 +37,7 @@ class FillModifier implements ModifierInterface
|
||||
$frame->getCore(),
|
||||
$this->position->getX(),
|
||||
$this->position->getY(),
|
||||
$this->color->toInt()
|
||||
$this->gd_color
|
||||
);
|
||||
}
|
||||
|
||||
@@ -47,7 +50,7 @@ class FillModifier implements ModifierInterface
|
||||
0,
|
||||
$frame->getSize()->getWidth() - 1,
|
||||
$frame->getSize()->getHeight() - 1,
|
||||
$this->color->toInt()
|
||||
$this->gd_color
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick;
|
||||
|
||||
use Imagick;
|
||||
use ImagickPixel;
|
||||
use Intervention\Image\Drivers\Abstract\AbstractColor;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
|
||||
class Color extends AbstractColor implements ColorInterface
|
||||
{
|
||||
public function __construct(protected ImagickPixel $pixel)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function getPixel(): ImagickPixel
|
||||
{
|
||||
return $this->pixel;
|
||||
}
|
||||
|
||||
public function red(): int
|
||||
{
|
||||
return intval(round($this->pixel->getColorValue(Imagick::COLOR_RED) * 255));
|
||||
}
|
||||
|
||||
public function green(): int
|
||||
{
|
||||
return intval(round($this->pixel->getColorValue(Imagick::COLOR_GREEN) * 255));
|
||||
}
|
||||
|
||||
public function blue(): int
|
||||
{
|
||||
return intval(round($this->pixel->getColorValue(Imagick::COLOR_BLUE) * 255));
|
||||
}
|
||||
|
||||
public function alpha(): float
|
||||
{
|
||||
return round($this->pixel->getColorValue(Imagick::COLOR_ALPHA), 2);
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
$this->red(),
|
||||
$this->green(),
|
||||
$this->blue(),
|
||||
$this->alpha()
|
||||
];
|
||||
}
|
||||
|
||||
public function toInt(): int
|
||||
{
|
||||
$r = $this->red();
|
||||
$g = $this->green();
|
||||
$b = $this->blue();
|
||||
$a = intval(round($this->alpha() * 255));
|
||||
|
||||
return intval(($a << 24) + ($r << 16) + ($g << 8) + $b);
|
||||
}
|
||||
}
|
32
src/Drivers/Imagick/ColorTransformer.php
Normal file
32
src/Drivers/Imagick/ColorTransformer.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick;
|
||||
|
||||
use ImagickPixel;
|
||||
use Intervention\Image\Colors\Parser;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
|
||||
class ColorTransformer
|
||||
{
|
||||
/**
|
||||
* Transforms ImagickPixel to own color object
|
||||
*
|
||||
* @param int $value
|
||||
* @return ColorInterface
|
||||
*/
|
||||
public static function colorFromPixel(ImagickPixel $pixel): ColorInterface
|
||||
{
|
||||
return Parser::parse($pixel->getColorAsString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms given color to the corresponding ImagickPixel
|
||||
*
|
||||
* @param ColorInterface $color
|
||||
* @return ImagickPixel
|
||||
*/
|
||||
public static function colorToPixel(ColorInterface $color): ImagickPixel
|
||||
{
|
||||
return new ImagickPixel($color->toString());
|
||||
}
|
||||
}
|
@@ -2,19 +2,20 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Abstract\Decoders\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class TransparentColorDecoder extends RgbArrayColorDecoder implements DecoderInterface
|
||||
class ColorObjectDecoder extends AbstractDecoder implements DecoderInterface
|
||||
{
|
||||
public function decode($input): ImageInterface|ColorInterface
|
||||
{
|
||||
if (! is_string($input) || strtolower($input) !== 'transparent') {
|
||||
if (! is_a($input, ColorInterface::class)) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
return parent::decode([0, 0, 0, 0]);
|
||||
return $input;
|
||||
}
|
||||
}
|
@@ -124,7 +124,9 @@ class Image extends AbstractImage implements ImageInterface, Iterator
|
||||
public function pickColor(int $x, int $y, int $frame_key = 0): ?ColorInterface
|
||||
{
|
||||
if ($frame = $this->getFrame($frame_key)) {
|
||||
return new Color($frame->getCore()->getImagePixelColor($x, $y));
|
||||
return ColorTransformer::colorFromPixel(
|
||||
$frame->getCore()->getImagePixelColor($x, $y)
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@@ -8,6 +8,7 @@ class InputHandler extends AbstractInputHandler
|
||||
{
|
||||
protected $decoders = [
|
||||
Decoders\ImageObjectDecoder::class,
|
||||
Decoders\ColorObjectDecoder::class,
|
||||
Decoders\FilePointerImageDecoder::class,
|
||||
Decoders\HtmlColorNameDecoder::class,
|
||||
Decoders\HexColorDecoder::class,
|
||||
|
@@ -4,19 +4,23 @@ namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
|
||||
use Imagick;
|
||||
use ImagickDraw;
|
||||
use Intervention\Image\Drivers\Imagick\Color;
|
||||
use ImagickPixel;
|
||||
use Intervention\Image\Drivers\Imagick\ColorTransformer;
|
||||
use Intervention\Image\Drivers\Imagick\Frame;
|
||||
use Intervention\Image\Geometry\Point;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class FillModifier implements ModifierInterface
|
||||
{
|
||||
protected ImagickPixel $pixel;
|
||||
|
||||
public function __construct(
|
||||
protected Color $color,
|
||||
protected ColorInterface $color,
|
||||
protected ?Point $position = null
|
||||
) {
|
||||
//
|
||||
$this->pixel = ColorTransformer::colorToPixel($color);
|
||||
}
|
||||
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
@@ -40,7 +44,7 @@ class FillModifier implements ModifierInterface
|
||||
);
|
||||
|
||||
$frame->getCore()->floodfillPaintImage(
|
||||
$this->color->getPixel(),
|
||||
$this->pixel,
|
||||
100,
|
||||
$target,
|
||||
$this->position->getX(),
|
||||
@@ -53,7 +57,7 @@ class FillModifier implements ModifierInterface
|
||||
protected function fillAllWithColor(Frame $frame): void
|
||||
{
|
||||
$draw = new ImagickDraw();
|
||||
$draw->setFillColor($this->color->getPixel());
|
||||
$draw->setFillColor($this->pixel);
|
||||
$draw->rectangle(
|
||||
0,
|
||||
0,
|
||||
|
14
src/Drivers/Imagick/Traits/CanReadColors.php
Normal file
14
src/Drivers/Imagick/Traits/CanReadColors.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Traits;
|
||||
|
||||
use ImagickPixel;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
|
||||
trait CanReadColors
|
||||
{
|
||||
public function colorToPixel(ColorInterface $color): ImagickPixel
|
||||
{
|
||||
return new ImagickPixel($color->toString());
|
||||
}
|
||||
}
|
@@ -9,4 +9,6 @@ interface ColorChannelInterface
|
||||
public function validate(mixed $value): mixed;
|
||||
public function min(): int;
|
||||
public function max(): int;
|
||||
public function toString(): string;
|
||||
public function __toString(): string;
|
||||
}
|
||||
|
@@ -8,14 +8,15 @@ use Intervention\Image\Colors\Rgba\Color as RgbaColor;
|
||||
|
||||
interface ColorInterface
|
||||
{
|
||||
// public function toRgb(): RgbColor;
|
||||
// public function toRgba(): RgbaColor;
|
||||
// public function toCmyk(): CmykColor;
|
||||
public function toRgb(): RgbColor;
|
||||
public function toRgba(): RgbaColor;
|
||||
public function toCmyk(): CmykColor;
|
||||
public function toArray(): array;
|
||||
public function toString(): string;
|
||||
public function __toString(): string;
|
||||
|
||||
// public function channels(): array;
|
||||
// public function channel(string $classname): ColorChannelInterface;
|
||||
// public function colorspace(): ColorspaceInterface;
|
||||
// public function toArray(): array;
|
||||
// public function convertTo(string|ColorspaceInterface $colorspace): ColorInterface;
|
||||
// public function __toString(): string;
|
||||
}
|
||||
|
32
tests/Colors/Cmyk/ParserTest.php
Normal file
32
tests/Colors/Cmyk/ParserTest.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Tests\Colors\Cmyk;
|
||||
|
||||
use Intervention\Image\Colors\Cmyk\Color;
|
||||
use Intervention\Image\Colors\Cmyk\Parser;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @requires extension gd
|
||||
* @covers \Intervention\Image\Colors\Cmyk\Parser
|
||||
*/
|
||||
class ParserTest extends TestCase
|
||||
{
|
||||
public function testParse(): void
|
||||
{
|
||||
$color = Parser::fromString('cmyk(100, 0, 0, 0)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([100, 0, 0, 0], $color->toArray());
|
||||
}
|
||||
|
||||
public function testFromString(): void
|
||||
{
|
||||
$color = Parser::fromString('cmyk(100, 0, 0, 0)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([100, 0, 0, 0], $color->toArray());
|
||||
|
||||
$color = Parser::fromString('cmyk(100%, 0%, 0%, 0%)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([100, 0, 0, 0], $color->toArray());
|
||||
}
|
||||
}
|
47
tests/Colors/ParserTest.php
Normal file
47
tests/Colors/ParserTest.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Tests\Colors;
|
||||
|
||||
use Intervention\Image\Colors\Cmyk\Color as CmykColor;
|
||||
use Intervention\Image\Colors\Rgb\Color as RgbColor;
|
||||
use Intervention\Image\Colors\Rgba\Color as RgbaColor;
|
||||
use Intervention\Image\Colors\Parser;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @requires extension gd
|
||||
* @covers \Intervention\Image\Colors\Parser
|
||||
*/
|
||||
class ParserTest extends TestCase
|
||||
{
|
||||
public function testParse(): void
|
||||
{
|
||||
$color = Parser::parse('ccc');
|
||||
$this->assertInstanceOf(RgbColor::class, $color);
|
||||
$this->assertEquals([204, 204, 204], $color->toArray());
|
||||
|
||||
$color = Parser::parse('rgb(204, 204, 204)');
|
||||
$this->assertInstanceOf(RgbColor::class, $color);
|
||||
$this->assertEquals([204, 204, 204], $color->toArray());
|
||||
|
||||
$color = Parser::parse('rgba(204, 204, 204, 1)');
|
||||
$this->assertInstanceOf(RgbaColor::class, $color);
|
||||
$this->assertEquals([204, 204, 204, 255], $color->toArray());
|
||||
|
||||
$color = Parser::parse('cccc');
|
||||
$this->assertInstanceOf(RgbColor::class, $color);
|
||||
$this->assertEquals([204, 204, 204, 204], $color->toArray());
|
||||
|
||||
$color = Parser::parse('cccccccc');
|
||||
$this->assertInstanceOf(RgbColor::class, $color);
|
||||
$this->assertEquals([204, 204, 204, 204], $color->toArray());
|
||||
|
||||
$color = Parser::parse('salmon');
|
||||
$this->assertInstanceOf(RgbColor::class, $color);
|
||||
$this->assertEquals('fa8072', $color->toHex());
|
||||
|
||||
$color = Parser::parse('cmyk(100, 100, 0,0)');
|
||||
$this->assertInstanceOf(CmykColor::class, $color);
|
||||
$this->assertEquals([100, 100, 0, 0], $color->toArray());
|
||||
}
|
||||
}
|
@@ -13,6 +13,21 @@ use Intervention\Image\Tests\TestCase;
|
||||
*/
|
||||
class ParserTest extends TestCase
|
||||
{
|
||||
public function testParse(): void
|
||||
{
|
||||
$color = Parser::parse('ccc');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([204, 204, 204], $color->toArray());
|
||||
|
||||
$color = Parser::parse('rgb(204, 204, 204)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([204, 204, 204], $color->toArray());
|
||||
|
||||
$color = Parser::parse('salmon');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals('fa8072', $color->toHex());
|
||||
}
|
||||
|
||||
public function testFromHex(): void
|
||||
{
|
||||
$color = Parser::fromHex('ccc');
|
||||
@@ -41,6 +56,14 @@ class ParserTest extends TestCase
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([204, 204, 204], $color->toArray());
|
||||
|
||||
$color = Parser::fromString('rgb(100%,20%,25%)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([255, 51, 64], $color->toArray());
|
||||
|
||||
$color = Parser::fromString('rgb(100%,74.8064%,25.2497%)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([255, 191, 64], $color->toArray());
|
||||
|
||||
$this->expectException(ColorException::class);
|
||||
(new Parser())->fromString('rgb(204,204,204,1)');
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
namespace Intervention\Image\Tests\Colors\Rgba;
|
||||
|
||||
use Intervention\Image\Colors\Rgba\Channels\Red as Channel;
|
||||
use Intervention\Image\Colors\Rgba\Channels\Alpha as Alpha;
|
||||
use Intervention\Image\Exceptions\ColorException;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
@@ -45,4 +46,22 @@ class ChannelTest extends TestCase
|
||||
$this->expectException(ColorException::class);
|
||||
new Channel(-1);
|
||||
}
|
||||
|
||||
public function testToString(): void
|
||||
{
|
||||
$channel = new Channel(255);
|
||||
$this->assertEquals("255", $channel->toString());
|
||||
|
||||
$channel = new Alpha(0);
|
||||
$this->assertEquals("0", $channel->toString());
|
||||
|
||||
$channel = new Alpha(51);
|
||||
$this->assertEquals("0.2", $channel->toString());
|
||||
|
||||
$channel = new Alpha(255);
|
||||
$this->assertEquals("1", $channel->toString());
|
||||
|
||||
$channel = new Alpha(170);
|
||||
$this->assertEquals("0.666667", $channel->toString());
|
||||
}
|
||||
}
|
||||
|
@@ -13,6 +13,21 @@ use Intervention\Image\Tests\TestCase;
|
||||
*/
|
||||
class ParserTest extends TestCase
|
||||
{
|
||||
public function testParse(): void
|
||||
{
|
||||
$color = Parser::parse('ccc');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([204, 204, 204, 255], $color->toArray());
|
||||
|
||||
$color = Parser::parse('rgba(204, 204, 204, 1)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([204, 204, 204, 255], $color->toArray());
|
||||
|
||||
$color = Parser::parse('salmon');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals('fa8072', $color->toHex());
|
||||
}
|
||||
|
||||
public function testFromHex(): void
|
||||
{
|
||||
$color = Parser::fromHex('ccc');
|
||||
@@ -62,6 +77,14 @@ class ParserTest extends TestCase
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([204, 204, 204, 51], $color->toArray());
|
||||
|
||||
$color = Parser::fromString('rgba(100%,20%,25%,100%)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([255, 51, 64, 255], $color->toArray());
|
||||
|
||||
$color = Parser::fromString('rgba(100%,74.8064%,25.2497%,100%)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals([255, 191, 64, 255], $color->toArray());
|
||||
|
||||
$this->expectException(ColorException::class);
|
||||
$color = Parser::fromString('rgba(204, 204, 204, 1.2)');
|
||||
}
|
||||
|
30
tests/Drivers/Gd/ColorTransformerTest.php
Normal file
30
tests/Drivers/Gd/ColorTransformerTest.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Tests\Drivers\Gd;
|
||||
|
||||
use Intervention\Image\Colors\Rgba\Color;
|
||||
use Intervention\Image\Drivers\Gd\ColorTransformer;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
class ColorTransformerTest extends TestCase
|
||||
{
|
||||
public function testFromInteger(): void
|
||||
{
|
||||
$result = ColorTransformer::colorFromInteger(850736919);
|
||||
$this->assertInstanceOf(Color::class, $result);
|
||||
$this->assertEquals([181, 55, 23, 155], $result->toArray());
|
||||
|
||||
$result = ColorTransformer::colorFromInteger(16777215);
|
||||
$this->assertInstanceOf(Color::class, $result);
|
||||
$this->assertEquals([255, 255, 255, 255], $result->toArray());
|
||||
}
|
||||
|
||||
public function testToInteger(): void
|
||||
{
|
||||
$result = ColorTransformer::colorToInteger(new Color(181, 55, 23, 155));
|
||||
$this->assertEquals(850736919, $result);
|
||||
|
||||
$result = ColorTransformer::colorToInteger(new Color(255, 255, 255, 255));
|
||||
$this->assertEquals(16777215, $result);
|
||||
}
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Intervention\Image\Tests\Drivers\Gd\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Gd\Color;
|
||||
use Intervention\Image\Colors\Rgb\Color;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\HexColorDecoder;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Intervention\Image\Tests\Drivers\Gd\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Gd\Color;
|
||||
use Intervention\Image\Colors\Rgb\Color;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\HtmlColorNameDecoder;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
|
@@ -2,7 +2,8 @@
|
||||
|
||||
namespace Intervention\Image\Tests\Drivers\Gd\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Gd\Color;
|
||||
use Intervention\Image\Colors\Rgb\Color as RgbColor;
|
||||
use Intervention\Image\Colors\Rgba\Color as RgbaColor;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\RgbStringColorDecoder;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
@@ -16,21 +17,15 @@ class RgbStringColorDecoderTest extends TestCase
|
||||
{
|
||||
$decoder = new RgbStringColorDecoder();
|
||||
$color = $decoder->decode('rgb(181, 55, 23)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals(181, $color->red());
|
||||
$this->assertEquals(55, $color->green());
|
||||
$this->assertEquals(23, $color->blue());
|
||||
$this->assertEquals(1, $color->alpha());
|
||||
$this->assertInstanceOf(RgbColor::class, $color);
|
||||
$this->assertEquals([181, 55, 23], $color->toArray());
|
||||
}
|
||||
|
||||
public function testDecodeRgba(): void
|
||||
{
|
||||
$decoder = new RgbStringColorDecoder();
|
||||
$color = $decoder->decode('rgba(181, 55, 23, 0.5)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals(181, $color->red());
|
||||
$this->assertEquals(55, $color->green());
|
||||
$this->assertEquals(23, $color->blue());
|
||||
$this->assertEquals(.5, $color->alpha());
|
||||
$this->assertInstanceOf(RgbaColor::class, $color);
|
||||
$this->assertEquals([181, 55, 23, 51], $color->toArray());
|
||||
}
|
||||
}
|
||||
|
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Tests\Drivers\Gd\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Gd\Color;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\TransparentColorDecoder;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @requires extension gd
|
||||
* @covers \Intervention\Image\Drivers\Gd\Decoders\TransparentColorDecoder
|
||||
*/
|
||||
class TransparentColorDecoderTest extends TestCase
|
||||
{
|
||||
public function testDecode(): void
|
||||
{
|
||||
$decoder = new TransparentColorDecoder();
|
||||
$color = $decoder->decode('transparent');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals(0, $color->red());
|
||||
$this->assertEquals(0, $color->green());
|
||||
$this->assertEquals(0, $color->blue());
|
||||
$this->assertEquals(0, $color->alpha());
|
||||
}
|
||||
}
|
37
tests/Drivers/Imagick/ColorTransformerTest.php
Normal file
37
tests/Drivers/Imagick/ColorTransformerTest.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Tests\Drivers\Imagick;
|
||||
|
||||
use ImagickPixel;
|
||||
use Intervention\Image\Colors\Rgba\Color;
|
||||
use Intervention\Image\Drivers\Imagick\ColorTransformer;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
class ColorTransformerTest extends TestCase
|
||||
{
|
||||
public function testFromPixel(): void
|
||||
{
|
||||
$result = ColorTransformer::colorFromPixel(new ImagickPixel('rgba(181, 55, 23, .6)'));
|
||||
$this->assertInstanceOf(Color::class, $result);
|
||||
$this->assertEquals([181, 55, 23, 153], $result->toArray());
|
||||
|
||||
$result = ColorTransformer::colorFromPixel(new ImagickPixel('rgba(255, 255, 255, 1)'));
|
||||
$this->assertInstanceOf(Color::class, $result);
|
||||
$this->assertEquals([255, 255, 255, 255], $result->toArray());
|
||||
}
|
||||
|
||||
public function testToPixel(): void
|
||||
{
|
||||
$result = ColorTransformer::colorToPixel(new Color(181, 55, 23, 153));
|
||||
$this->assertInstanceOf(ImagickPixel::class, $result);
|
||||
$this->assertEquals('srgba(181,55,23,0.6)', $result->getColorAsString());
|
||||
|
||||
$result = ColorTransformer::colorToPixel(new Color(255, 255, 255, 255));
|
||||
$this->assertInstanceOf(ImagickPixel::class, $result);
|
||||
$this->assertEquals('srgba(255,255,255,1)', $result->getColorAsString());
|
||||
|
||||
$result = ColorTransformer::colorToPixel(new Color(255, 255, 255, 170));
|
||||
$this->assertInstanceOf(ImagickPixel::class, $result);
|
||||
$this->assertEquals('srgba(255,255,255,0.699992)', $result->getColorAsString());
|
||||
}
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Intervention\Image\Tests\Drivers\Imagick\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Imagick\Color;
|
||||
use Intervention\Image\Colors\Rgb\Color;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\HtmlColorNameDecoder;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
|
@@ -2,7 +2,8 @@
|
||||
|
||||
namespace Intervention\Image\Tests\Drivers\Imagick\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Imagick\Color;
|
||||
use Intervention\Image\Colors\Rgb\Color as RgbColor;
|
||||
use Intervention\Image\Colors\Rgba\Color as RgbaColor;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\RgbStringColorDecoder;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
@@ -16,21 +17,15 @@ class RgbStringColorDecoderTest extends TestCase
|
||||
{
|
||||
$decoder = new RgbStringColorDecoder();
|
||||
$color = $decoder->decode('rgb(181, 55, 23)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals(181, $color->red());
|
||||
$this->assertEquals(55, $color->green());
|
||||
$this->assertEquals(23, $color->blue());
|
||||
$this->assertEquals(1, $color->alpha());
|
||||
$this->assertInstanceOf(RgbColor::class, $color);
|
||||
$this->assertEquals([181, 55, 23], $color->toArray());
|
||||
}
|
||||
|
||||
public function testDecodeRgba(): void
|
||||
{
|
||||
$decoder = new RgbStringColorDecoder();
|
||||
$color = $decoder->decode('rgba(181, 55, 23, 0.5)');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals(181, $color->red());
|
||||
$this->assertEquals(55, $color->green());
|
||||
$this->assertEquals(23, $color->blue());
|
||||
$this->assertEquals(.5, $color->alpha());
|
||||
$color = $decoder->decode('rgba(181, 55, 23, 0.2)');
|
||||
$this->assertInstanceOf(RgbaColor::class, $color);
|
||||
$this->assertEquals([181, 55, 23, 51], $color->toArray());
|
||||
}
|
||||
}
|
||||
|
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Intervention\Image\Tests\Drivers\Imagick\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Imagick\Color;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\TransparentColorDecoder;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @requires extension imagick
|
||||
* @covers \Intervention\Image\Drivers\Imagick\Decoders\TransparentColorDecoder
|
||||
*/
|
||||
class TransparentColorDecoderTest extends TestCase
|
||||
{
|
||||
public function testDecode(): void
|
||||
{
|
||||
$decoder = new TransparentColorDecoder();
|
||||
$color = $decoder->decode('transparent');
|
||||
$this->assertInstanceOf(Color::class, $color);
|
||||
$this->assertEquals(0, $color->red());
|
||||
$this->assertEquals(0, $color->green());
|
||||
$this->assertEquals(0, $color->blue());
|
||||
$this->assertEquals(0, $color->alpha());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user