mirror of
https://github.com/Intervention/image.git
synced 2025-01-17 12:18:14 +01:00
Merge pull request #1350 from Intervention/feature/config
Configuration API
This commit is contained in:
commit
8d50e50dcb
@ -68,7 +68,7 @@ testing, it must also run without errors.
|
||||
Check the analyzer by running the following command.
|
||||
|
||||
```bash
|
||||
./vendor/bin/phpstan analyze --memory-limit=512M --level=4 ./src
|
||||
./vendor/bin/phpstan analyze --memory-limit=512M ./src
|
||||
```
|
||||
|
||||
Or by using the project's Docker environment.
|
||||
|
16
readme.md
16
readme.md
@ -66,22 +66,6 @@ $encoded->save('images/example.jpg');
|
||||
- GD Library
|
||||
- Imagick PHP extension
|
||||
|
||||
## Development & Testing
|
||||
|
||||
This package contains a Docker image for building a test suite and an analysis
|
||||
container. You must have Docker installed on your system to run all tests using
|
||||
the following command.
|
||||
|
||||
```bash
|
||||
docker-compose run --rm --build tests
|
||||
```
|
||||
|
||||
Run the static analyzer on the code base.
|
||||
|
||||
```bash
|
||||
docker-compose run --rm --build analysis
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
If you discover any security related issues, please email oliver@intervention.io directly.
|
||||
|
@ -10,7 +10,7 @@ use Intervention\Image\Colors\Cmyk\Channels\Magenta;
|
||||
use Intervention\Image\Colors\Cmyk\Channels\Yellow;
|
||||
use Intervention\Image\Colors\Cmyk\Channels\Key;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Drivers\AbstractInputHandler;
|
||||
use Intervention\Image\InputHandler;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
@ -44,11 +44,9 @@ class Color extends AbstractColor
|
||||
*/
|
||||
public static function create(mixed $input): ColorInterface
|
||||
{
|
||||
return (new class ([
|
||||
return InputHandler::withDecoders([
|
||||
Decoders\StringColorDecoder::class,
|
||||
]) extends AbstractInputHandler
|
||||
{
|
||||
})->handle($input);
|
||||
])->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,7 +9,7 @@ use Intervention\Image\Colors\Hsl\Channels\Hue;
|
||||
use Intervention\Image\Colors\Hsl\Channels\Luminance;
|
||||
use Intervention\Image\Colors\Hsl\Channels\Saturation;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Drivers\AbstractInputHandler;
|
||||
use Intervention\Image\InputHandler;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
@ -43,11 +43,9 @@ class Color extends AbstractColor
|
||||
*/
|
||||
public static function create(mixed $input): ColorInterface
|
||||
{
|
||||
return (new class ([
|
||||
return InputHandler::withDecoders([
|
||||
Decoders\StringColorDecoder::class,
|
||||
]) extends AbstractInputHandler
|
||||
{
|
||||
})->handle($input);
|
||||
])->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,7 +9,7 @@ use Intervention\Image\Colors\Hsv\Channels\Hue;
|
||||
use Intervention\Image\Colors\Hsv\Channels\Saturation;
|
||||
use Intervention\Image\Colors\Hsv\Channels\Value;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Drivers\AbstractInputHandler;
|
||||
use Intervention\Image\InputHandler;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
@ -43,11 +43,9 @@ class Color extends AbstractColor
|
||||
*/
|
||||
public static function create(mixed $input): ColorInterface
|
||||
{
|
||||
return (new class ([
|
||||
return InputHandler::withDecoders([
|
||||
Decoders\StringColorDecoder::class,
|
||||
]) extends AbstractInputHandler
|
||||
{
|
||||
})->handle($input);
|
||||
])->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,7 +9,7 @@ use Intervention\Image\Colors\Rgb\Channels\Blue;
|
||||
use Intervention\Image\Colors\Rgb\Channels\Green;
|
||||
use Intervention\Image\Colors\Rgb\Channels\Red;
|
||||
use Intervention\Image\Colors\Rgb\Channels\Alpha;
|
||||
use Intervention\Image\Drivers\AbstractInputHandler;
|
||||
use Intervention\Image\InputHandler;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
@ -53,14 +53,12 @@ class Color extends AbstractColor
|
||||
*/
|
||||
public static function create(mixed $input): ColorInterface
|
||||
{
|
||||
return (new class ([
|
||||
return InputHandler::withDecoders([
|
||||
Decoders\HexColorDecoder::class,
|
||||
Decoders\StringColorDecoder::class,
|
||||
Decoders\TransparentColorDecoder::class,
|
||||
Decoders\HtmlColornameDecoder::class,
|
||||
]) extends AbstractInputHandler
|
||||
{
|
||||
})->handle($input);
|
||||
])->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
|
73
src/Config.php
Normal file
73
src/Config.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image;
|
||||
|
||||
use Intervention\Image\Exceptions\InputException;
|
||||
|
||||
class Config
|
||||
{
|
||||
/**
|
||||
* Create config object instance
|
||||
*
|
||||
* @param bool $autoOrientation
|
||||
* @param bool $decodeAnimation
|
||||
* @param mixed $blendingColor
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
public bool $autoOrientation = true,
|
||||
public bool $decodeAnimation = true,
|
||||
public mixed $blendingColor = 'ffffff',
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set values of given config options
|
||||
*
|
||||
* @param mixed $options
|
||||
* @throws InputException
|
||||
* @return Config
|
||||
*/
|
||||
public function setOptions(mixed ...$options): self
|
||||
{
|
||||
foreach ($this->prepareOptions($options) as $name => $value) {
|
||||
if (!property_exists($this, $name)) {
|
||||
throw new InputException('Property ' . $name . ' does not exists for ' . $this::class . '.');
|
||||
}
|
||||
|
||||
$this->{$name} = $value;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method makes it possible to call self::setOptions() with a single
|
||||
* array instead of named parameters
|
||||
*
|
||||
* @param array<mixed> $options
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function prepareOptions(array $options): array
|
||||
{
|
||||
if (count($options) === 0) {
|
||||
return $options;
|
||||
}
|
||||
|
||||
if (count($options) > 1) {
|
||||
return $options;
|
||||
}
|
||||
|
||||
if (!array_key_exists(0, $options)) {
|
||||
return $options;
|
||||
}
|
||||
|
||||
if (!is_array($options[0])) {
|
||||
return $options;
|
||||
}
|
||||
|
||||
return $options[0];
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Decoders;
|
||||
namespace Intervention\Image\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
@ -11,6 +11,11 @@ use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class ColorObjectDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see DecoderInterface::decode()
|
||||
*/
|
||||
public function decode(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
if (!is_a($input, ColorInterface::class)) {
|
@ -4,8 +4,24 @@ declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableDecoder;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
|
||||
class ImageObjectDecoder extends SpecializableDecoder
|
||||
class ImageObjectDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see DecoderInterface::decode()
|
||||
*/
|
||||
public function decode(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
if (!is_a($input, ImageInterface::class)) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
}
|
||||
|
@ -6,54 +6,14 @@ namespace Intervention\Image\Drivers;
|
||||
|
||||
use Exception;
|
||||
use Intervention\Image\Collection;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Exceptions\RuntimeException;
|
||||
use Intervention\Image\Interfaces\CollectionInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Traits\CanBuildFilePointer;
|
||||
|
||||
abstract class AbstractDecoder implements DecoderInterface
|
||||
{
|
||||
use CanBuildFilePointer;
|
||||
|
||||
public function __construct(protected ?self $successor = null)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to decode given input to image or color object
|
||||
*
|
||||
* @param mixed $input
|
||||
* @throws RuntimeException
|
||||
* @return ImageInterface|ColorInterface
|
||||
*/
|
||||
final public function handle(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
try {
|
||||
$decoded = $this->decode($input);
|
||||
} catch (DecoderException $e) {
|
||||
if (!$this->hasSuccessor()) {
|
||||
throw new DecoderException($e->getMessage());
|
||||
}
|
||||
|
||||
return $this->successor->handle($input);
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if current decoder has a successor
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasSuccessor(): bool
|
||||
{
|
||||
return $this->successor !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given input is GIF data format
|
||||
*
|
||||
|
@ -4,12 +4,16 @@ declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Drivers;
|
||||
|
||||
use Intervention\Image\Config;
|
||||
use Intervention\Image\Exceptions\DriverException;
|
||||
use Intervention\Image\Exceptions\NotSupportedException;
|
||||
use Intervention\Image\InputHandler;
|
||||
use Intervention\Image\Interfaces\AnalyzerInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\DriverInterface;
|
||||
use Intervention\Image\Interfaces\EncoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
use Intervention\Image\Interfaces\SpecializableInterface;
|
||||
use Intervention\Image\Interfaces\SpecializedInterface;
|
||||
@ -17,14 +21,41 @@ use ReflectionClass;
|
||||
|
||||
abstract class AbstractDriver implements DriverInterface
|
||||
{
|
||||
/**
|
||||
* Driver options
|
||||
*/
|
||||
protected Config $config;
|
||||
|
||||
/**
|
||||
* @throws DriverException
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = new Config();
|
||||
$this->checkHealth();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see DriverInterface::config()
|
||||
*/
|
||||
public function config(): Config
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see DriverInterface::handleInput()
|
||||
*/
|
||||
public function handleInput(mixed $input, array $decoders = []): ImageInterface|ColorInterface
|
||||
{
|
||||
return InputHandler::withDecoders($decoders, $this)->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
@ -38,8 +69,10 @@ abstract class AbstractDriver implements DriverInterface
|
||||
return $object;
|
||||
}
|
||||
|
||||
// return directly if object is already specialized
|
||||
if ($object instanceof SpecializedInterface) {
|
||||
// return directly and only attach driver if object is already specialized
|
||||
if (($object instanceof SpecializedInterface)) {
|
||||
$object->setDriver($this);
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
@ -54,7 +87,7 @@ abstract class AbstractDriver implements DriverInterface
|
||||
);
|
||||
}
|
||||
|
||||
// create driver specialized object with specializable properties of generic object
|
||||
// create a driver specialized object with the specializable properties of generic object
|
||||
$specialized = (new $specialized_classname(...$object->specializable()));
|
||||
|
||||
// attach driver
|
||||
|
@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Drivers;
|
||||
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\InputHandlerInterface;
|
||||
|
||||
abstract class AbstractInputHandler implements InputHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Decoder classnames in hierarchical order
|
||||
*
|
||||
* @var array<string|DecoderInterface>
|
||||
*/
|
||||
protected array $decoders = [];
|
||||
|
||||
/**
|
||||
* Create new input handler instance with given decoder classnames
|
||||
*
|
||||
* @param array<string|DecoderInterface> $decoders
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $decoders = [])
|
||||
{
|
||||
$this->decoders = count($decoders) ? $decoders : $this->decoders;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see InputHandlerInterface::handle()
|
||||
*/
|
||||
public function handle($input): ImageInterface|ColorInterface
|
||||
{
|
||||
return $this->chain()->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stack the decoder array into a nested decoder object
|
||||
*
|
||||
* @throws DecoderException
|
||||
* @return AbstractDecoder
|
||||
*/
|
||||
protected function chain(): AbstractDecoder
|
||||
{
|
||||
if (count($this->decoders) == 0) {
|
||||
throw new DecoderException('No decoders found in ' . $this::class);
|
||||
}
|
||||
|
||||
// get last decoder in stack
|
||||
list($decoder) = array_slice(array_reverse($this->decoders), 0, 1);
|
||||
$chain = ($decoder instanceof DecoderInterface) ? $decoder : new $decoder();
|
||||
|
||||
// only accept DecoderInterface
|
||||
if (!($chain instanceof DecoderInterface)) {
|
||||
throw new DecoderException('Decoder must implement in ' . DecoderInterface::class);
|
||||
}
|
||||
|
||||
// build decoder chain
|
||||
foreach (array_slice(array_reverse($this->decoders), 1) as $decoder) {
|
||||
$chain = ($decoder instanceof DecoderInterface) ? new ($decoder::class)($chain) : new $decoder($chain);
|
||||
}
|
||||
|
||||
return $chain;
|
||||
}
|
||||
}
|
@ -8,14 +8,11 @@ use Intervention\Image\Exceptions\RuntimeException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\Traits\CanDecodeGif;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Modifiers\AlignRotationModifier;
|
||||
|
||||
class BinaryImageDecoder extends NativeObjectDecoder implements DecoderInterface
|
||||
{
|
||||
use CanDecodeGif;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
@ -63,7 +60,9 @@ class BinaryImageDecoder extends NativeObjectDecoder implements DecoderInterface
|
||||
}
|
||||
|
||||
// adjust image orientation
|
||||
$image->modify(new AlignRotationModifier());
|
||||
if ($this->driver()->config()->autoOrientation) {
|
||||
$image->modify(new AlignRotationModifier());
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class ColorObjectDecoder extends AbstractDecoder implements DecoderInterface
|
||||
{
|
||||
public function decode(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
if (!is_a($input, ColorInterface::class)) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\Gd\Decoders\Traits\CanDecodeGif;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
@ -13,8 +12,6 @@ use Intervention\Image\Modifiers\AlignRotationModifier;
|
||||
|
||||
class FilePathImageDecoder extends NativeObjectDecoder implements DecoderInterface
|
||||
{
|
||||
use CanDecodeGif;
|
||||
|
||||
public function decode(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
if (!$this->isFile($input)) {
|
||||
@ -53,7 +50,9 @@ class FilePathImageDecoder extends NativeObjectDecoder implements DecoderInterfa
|
||||
$image->setExif($this->extractExifData($input));
|
||||
|
||||
// adjust image orientation
|
||||
$image->modify(new AlignRotationModifier());
|
||||
if ($this->driver()->config()->autoOrientation) {
|
||||
$image->modify(new AlignRotationModifier());
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class ImageObjectDecoder extends AbstractDecoder implements DecoderInterface
|
||||
{
|
||||
public function decode(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
if (!is_a($input, ImageInterface::class)) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
}
|
@ -5,13 +5,15 @@ declare(strict_types=1);
|
||||
namespace Intervention\Image\Drivers\Gd\Decoders;
|
||||
|
||||
use GdImage;
|
||||
use Intervention\Gif\Decoder as GifDecoder;
|
||||
use Intervention\Gif\Splitter as GifSplitter;
|
||||
use Intervention\Image\Drivers\Gd\Core;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Drivers\Gd\Frame;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Exceptions\RuntimeException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class NativeObjectDecoder extends AbstractDecoder
|
||||
{
|
||||
@ -38,10 +40,67 @@ class NativeObjectDecoder extends AbstractDecoder
|
||||
|
||||
// build image instance
|
||||
return new Image(
|
||||
new Driver(),
|
||||
$this->driver(),
|
||||
new Core([
|
||||
new Frame($input)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode image from given GIF source which can be either a file path or binary data
|
||||
*
|
||||
* Depending on the configuration, this is taken over by the native GD function
|
||||
* or, if animations are required, by our own extended decoder.
|
||||
*
|
||||
* @param mixed $input
|
||||
* @throws RuntimeException
|
||||
* @return ImageInterface
|
||||
*/
|
||||
protected function decodeGif(mixed $input): ImageInterface
|
||||
{
|
||||
// create non-animated image depending on config
|
||||
if (!$this->driver()->config()->decodeAnimation) {
|
||||
$native = match (true) {
|
||||
$this->isGifFormat($input) => @imagecreatefromstring($input),
|
||||
default => @imagecreatefromgif($input),
|
||||
};
|
||||
|
||||
if ($native === false) {
|
||||
throw new DecoderException('Unable to decode input.');
|
||||
}
|
||||
|
||||
$image = self::decode($native);
|
||||
$image->origin()->setMediaType('image/gif');
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
// create empty core
|
||||
$core = new Core();
|
||||
|
||||
$gif = GifDecoder::decode($input);
|
||||
$splitter = GifSplitter::create($gif)->split();
|
||||
$delays = $splitter->getDelays();
|
||||
|
||||
// set loops on core
|
||||
if ($loops = $gif->getMainApplicationExtension()?->getLoops()) {
|
||||
$core->setLoops($loops);
|
||||
}
|
||||
|
||||
// add GDImage instances to core
|
||||
foreach ($splitter->coalesceToResources() as $key => $native) {
|
||||
$core->push(
|
||||
new Frame($native, $delays[$key] / 100)
|
||||
);
|
||||
}
|
||||
|
||||
// create (possibly) animated image
|
||||
$image = new Image($this->driver(), $core);
|
||||
|
||||
// set media type
|
||||
$image->origin()->setMediaType('image/gif');
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
||||
|
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd\Decoders\Traits;
|
||||
|
||||
use Intervention\Gif\Decoder as GifDecoder;
|
||||
use Intervention\Gif\Splitter as GifSplitter;
|
||||
use Intervention\Image\Drivers\Gd\Core;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Drivers\Gd\Frame;
|
||||
use Intervention\Image\Exceptions\RuntimeException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
trait CanDecodeGif
|
||||
{
|
||||
/**
|
||||
* Decode image from given GIF source which can be either a file path or binary data
|
||||
*
|
||||
* @param mixed $input
|
||||
* @throws RuntimeException
|
||||
* @return ImageInterface
|
||||
*/
|
||||
protected function decodeGif(mixed $input): ImageInterface
|
||||
{
|
||||
$gif = GifDecoder::decode($input);
|
||||
$splitter = GifSplitter::create($gif)->split();
|
||||
$delays = $splitter->getDelays();
|
||||
|
||||
// build core
|
||||
$core = new Core();
|
||||
|
||||
// set loops on core
|
||||
if ($loops = $gif->getMainApplicationExtension()?->getLoops()) {
|
||||
$core->setLoops($loops);
|
||||
}
|
||||
|
||||
// add GDImage instances to core
|
||||
foreach ($splitter->coalesceToResources() as $key => $native) {
|
||||
$core->push(
|
||||
(new Frame($native))->setDelay($delays[$key] / 100)
|
||||
);
|
||||
}
|
||||
|
||||
// create image
|
||||
$image = new Image(new Driver(), $core);
|
||||
|
||||
// set media type
|
||||
$image->origin()->setMediaType('image/gif');
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
@ -11,7 +11,6 @@ use Intervention\Image\Exceptions\RuntimeException;
|
||||
use Intervention\Image\Format;
|
||||
use Intervention\Image\FileExtension;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorProcessorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
use Intervention\Image\Interfaces\DriverInterface;
|
||||
@ -113,16 +112,6 @@ class Driver extends AbstractDriver
|
||||
return call_user_func($animation);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see DriverInterface::handleInput()
|
||||
*/
|
||||
public function handleInput(mixed $input, array $decoders = []): ImageInterface|ColorInterface
|
||||
{
|
||||
return (new InputHandler($this->specializeMultiple($decoders)))->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
|
@ -14,7 +14,14 @@ class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface
|
||||
{
|
||||
public function encode(ImageInterface $image): EncodedImage
|
||||
{
|
||||
$output = Cloner::cloneBlended($image->core()->native(), background: $image->blendingColor());
|
||||
$blendingColor = $this->driver()->handleInput(
|
||||
$this->driver()->config()->blendingColor
|
||||
);
|
||||
|
||||
$output = Cloner::cloneBlended(
|
||||
$image->core()->native(),
|
||||
background: $blendingColor
|
||||
);
|
||||
|
||||
$data = $this->buffered(function () use ($output) {
|
||||
imageinterlace($output, $this->progressive);
|
||||
|
@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Drivers\Gd;
|
||||
|
||||
use Intervention\Image\Colors\Rgb\Decoders\HexColorDecoder as RgbHexColorDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\StringColorDecoder as RgbStringColorDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\HtmlColornameDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\TransparentColorDecoder;
|
||||
use Intervention\Image\Colors\Cmyk\Decoders\StringColorDecoder as CmykStringColorDecoder;
|
||||
use Intervention\Image\Colors\Hsv\Decoders\StringColorDecoder as HsvStringColorDecoder;
|
||||
use Intervention\Image\Colors\Hsl\Decoders\StringColorDecoder as HslStringColorDecoder;
|
||||
use Intervention\Image\Drivers\AbstractInputHandler;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\ImageObjectDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\ColorObjectDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\FilePointerImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\BinaryImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\DataUriImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\Base64ImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\NativeObjectDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\SplFileInfoImageDecoder;
|
||||
|
||||
class InputHandler extends AbstractInputHandler
|
||||
{
|
||||
/**
|
||||
* Decoders in hierarchical order
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected array $decoders = [
|
||||
NativeObjectDecoder::class,
|
||||
ImageObjectDecoder::class,
|
||||
ColorObjectDecoder::class,
|
||||
RgbHexColorDecoder::class,
|
||||
RgbStringColorDecoder::class,
|
||||
CmykStringColorDecoder::class,
|
||||
HsvStringColorDecoder::class,
|
||||
HslStringColorDecoder::class,
|
||||
TransparentColorDecoder::class,
|
||||
HtmlColornameDecoder::class,
|
||||
FilePointerImageDecoder::class,
|
||||
FilePathImageDecoder::class,
|
||||
SplFileInfoImageDecoder::class,
|
||||
BinaryImageDecoder::class,
|
||||
DataUriImageDecoder::class,
|
||||
Base64ImageDecoder::class,
|
||||
];
|
||||
}
|
@ -12,7 +12,7 @@ class AlignRotationModifier extends GenericAlignRotationModifier implements Spec
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
return match ($image->exif('IFD0.Orientation')) {
|
||||
$image = match ($image->exif('IFD0.Orientation')) {
|
||||
2 => $image->flop(),
|
||||
3 => $image->rotate(180),
|
||||
4 => $image->rotate(180)->flop(),
|
||||
@ -22,5 +22,29 @@ class AlignRotationModifier extends GenericAlignRotationModifier implements Spec
|
||||
8 => $image->rotate(90),
|
||||
default => $image
|
||||
};
|
||||
|
||||
return $this->markAligned($image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set exif data of image to top-left orientation, marking the image as
|
||||
* aligned and making sure the rotation correction process is not
|
||||
* performed again.
|
||||
*
|
||||
* @param ImageInterface $image
|
||||
* @return ImageInterface
|
||||
*/
|
||||
private function markAligned(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$exif = $image->exif()->map(function ($item) {
|
||||
if (is_array($item) && array_key_exists('Orientation', $item)) {
|
||||
$item['Orientation'] = 1;
|
||||
return $item;
|
||||
}
|
||||
|
||||
return $item;
|
||||
});
|
||||
|
||||
return $image->setExif($exif);
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class BlendTransparencyModifier extends GenericBlendTransparencyModifier impleme
|
||||
{
|
||||
// decode blending color
|
||||
$color = $this->driver()->handleInput(
|
||||
$this->color ? $this->color : $image->blendingColor()
|
||||
$this->color ? $this->color : $this->driver()->config()->blendingColor
|
||||
);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
|
@ -23,7 +23,9 @@ class ContainModifier extends GenericContainModifier implements SpecializedInter
|
||||
$crop = $this->getCropSize($image);
|
||||
$resize = $this->getResizeSize($image);
|
||||
$background = $this->driver()->handleInput($this->background);
|
||||
$blendingColor = $image->blendingColor();
|
||||
$blendingColor = $this->driver()->handleInput(
|
||||
$this->driver()->config()->blendingColor
|
||||
);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
$this->modify($frame, $crop, $resize, $background, $blendingColor);
|
||||
|
@ -31,9 +31,13 @@ class QuantizeColorsModifier extends GenericQuantizeColorsModifier implements Sp
|
||||
$this->driver()->handleInput($this->background)
|
||||
);
|
||||
|
||||
$blendingColor = $this->driver()->handleInput(
|
||||
$this->driver()->config()->blendingColor
|
||||
);
|
||||
|
||||
foreach ($image as $frame) {
|
||||
// create new image for color quantization
|
||||
$reduced = Cloner::cloneEmpty($frame->native(), background: $image->blendingColor());
|
||||
$reduced = Cloner::cloneEmpty($frame->native(), background: $blendingColor);
|
||||
|
||||
// fill with background
|
||||
imagefill($reduced, 0, 0, $background);
|
||||
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick\Decoders;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class ImageObjectDecoder extends SpecializableDecoder
|
||||
{
|
||||
public function decode(mixed $input): ImageInterface|ColorInterface
|
||||
{
|
||||
if (!is_a($input, ImageInterface::class)) {
|
||||
throw new DecoderException('Unable to decode input');
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
}
|
@ -6,13 +6,13 @@ namespace Intervention\Image\Drivers\Imagick\Decoders;
|
||||
|
||||
use Imagick;
|
||||
use Intervention\Image\Drivers\Imagick\Core;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
use Intervention\Image\Drivers\SpecializableDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Modifiers\AlignRotationModifier;
|
||||
use Intervention\Image\Modifiers\RemoveAnimationModifier;
|
||||
|
||||
class NativeObjectDecoder extends SpecializableDecoder
|
||||
{
|
||||
@ -33,13 +33,21 @@ class NativeObjectDecoder extends SpecializableDecoder
|
||||
$input = $input->coalesceImages();
|
||||
}
|
||||
|
||||
// create image object
|
||||
$image = new Image(
|
||||
new Driver(),
|
||||
$this->driver(),
|
||||
new Core($input)
|
||||
);
|
||||
|
||||
// discard animation depending on config
|
||||
if (!$this->driver()->config()->decodeAnimation) {
|
||||
$image->modify(new RemoveAnimationModifier());
|
||||
}
|
||||
|
||||
// adjust image rotatation
|
||||
$image->modify(new AlignRotationModifier());
|
||||
if ($this->driver()->config()->autoOrientation) {
|
||||
$image->modify(new AlignRotationModifier());
|
||||
}
|
||||
|
||||
// set media type on origin
|
||||
$image->origin()->setMediaType($input->getImageMimeType());
|
||||
|
@ -13,7 +13,6 @@ use Intervention\Image\Exceptions\RuntimeException;
|
||||
use Intervention\Image\Format;
|
||||
use Intervention\Image\FileExtension;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorProcessorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
use Intervention\Image\Interfaces\DriverInterface;
|
||||
@ -116,16 +115,6 @@ class Driver extends AbstractDriver
|
||||
return call_user_func($animation);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see DriverInterface::handleInput()
|
||||
*/
|
||||
public function handleInput(mixed $input, array $decoders = []): ImageInterface|ColorInterface
|
||||
{
|
||||
return (new InputHandler($this->specializeMultiple($decoders)))->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
|
@ -16,11 +16,14 @@ class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface
|
||||
{
|
||||
$format = 'jpeg';
|
||||
$compression = Imagick::COMPRESSION_JPEG;
|
||||
$blendingColor = $this->driver()->handleInput(
|
||||
$this->driver()->config()->blendingColor
|
||||
);
|
||||
|
||||
// resolve blending color because jpeg has no transparency
|
||||
$background = $this->driver()
|
||||
->colorProcessor($image->colorspace())
|
||||
->colorToNative($image->blendingColor());
|
||||
->colorToNative($blendingColor);
|
||||
|
||||
// set alpha value to 1 because Imagick renders
|
||||
// possible full transparent colors as black
|
||||
|
@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Drivers\Imagick;
|
||||
|
||||
use Intervention\Image\Colors\Rgb\Decoders\HexColorDecoder as RgbHexColorDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\StringColorDecoder as RgbStringColorDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\HtmlColornameDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\TransparentColorDecoder;
|
||||
use Intervention\Image\Colors\Cmyk\Decoders\StringColorDecoder as CmykStringColorDecoder;
|
||||
use Intervention\Image\Colors\Hsv\Decoders\StringColorDecoder as HsvStringColorDecoder;
|
||||
use Intervention\Image\Colors\Hsl\Decoders\StringColorDecoder as HslStringColorDecoder;
|
||||
use Intervention\Image\Drivers\AbstractInputHandler;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\ImageObjectDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\ColorObjectDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\FilePointerImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\BinaryImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\DataUriImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\Base64ImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\NativeObjectDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\SplFileInfoImageDecoder;
|
||||
|
||||
class InputHandler extends AbstractInputHandler
|
||||
{
|
||||
/**
|
||||
* Decoders in hierarchical order
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected array $decoders = [
|
||||
NativeObjectDecoder::class,
|
||||
ImageObjectDecoder::class,
|
||||
ColorObjectDecoder::class,
|
||||
RgbHexColorDecoder::class,
|
||||
RgbStringColorDecoder::class,
|
||||
CmykStringColorDecoder::class,
|
||||
HsvStringColorDecoder::class,
|
||||
HslStringColorDecoder::class,
|
||||
TransparentColorDecoder::class,
|
||||
HtmlColornameDecoder::class,
|
||||
FilePointerImageDecoder::class,
|
||||
FilePathImageDecoder::class,
|
||||
SplFileInfoImageDecoder::class,
|
||||
BinaryImageDecoder::class,
|
||||
DataUriImageDecoder::class,
|
||||
Base64ImageDecoder::class,
|
||||
];
|
||||
}
|
@ -19,30 +19,30 @@ class AlignRotationModifier extends GenericAlignRotationModifier implements Spec
|
||||
break;
|
||||
|
||||
case Imagick::ORIENTATION_BOTTOMRIGHT: // 3
|
||||
$image->core()->native()->rotateimage("#000", 180);
|
||||
$image->core()->native()->rotateImage("#000", 180);
|
||||
break;
|
||||
|
||||
case Imagick::ORIENTATION_BOTTOMLEFT: // 4
|
||||
$image->core()->native()->rotateimage("#000", 180);
|
||||
$image->core()->native()->rotateImage("#000", 180);
|
||||
$image->core()->native()->flopImage();
|
||||
break;
|
||||
|
||||
case Imagick::ORIENTATION_LEFTTOP: // 5
|
||||
$image->core()->native()->rotateimage("#000", -270);
|
||||
$image->core()->native()->rotateImage("#000", -270);
|
||||
$image->core()->native()->flopImage();
|
||||
break;
|
||||
|
||||
case Imagick::ORIENTATION_RIGHTTOP: // 6
|
||||
$image->core()->native()->rotateimage("#000", -270);
|
||||
$image->core()->native()->rotateImage("#000", -270);
|
||||
break;
|
||||
|
||||
case Imagick::ORIENTATION_RIGHTBOTTOM: // 7
|
||||
$image->core()->native()->rotateimage("#000", -90);
|
||||
$image->core()->native()->rotateImage("#000", -90);
|
||||
$image->core()->native()->flopImage();
|
||||
break;
|
||||
|
||||
case Imagick::ORIENTATION_LEFTBOTTOM: // 8
|
||||
$image->core()->native()->rotateimage("#000", -90);
|
||||
$image->core()->native()->rotateImage("#000", -90);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ class BlendTransparencyModifier extends GenericBlendTransparencyModifier impleme
|
||||
{
|
||||
// decode blending color
|
||||
$color = $this->driver()->handleInput(
|
||||
$this->color ? $this->color : $image->blendingColor()
|
||||
$this->color ? $this->color : $this->driver()->config()->blendingColor
|
||||
);
|
||||
|
||||
// get imagickpixel from color
|
||||
|
@ -13,7 +13,6 @@ use Intervention\Image\Analyzers\PixelColorsAnalyzer;
|
||||
use Intervention\Image\Analyzers\ProfileAnalyzer;
|
||||
use Intervention\Image\Analyzers\ResolutionAnalyzer;
|
||||
use Intervention\Image\Analyzers\WidthAnalyzer;
|
||||
use Intervention\Image\Colors\Rgb\Color;
|
||||
use Intervention\Image\Encoders\AutoEncoder;
|
||||
use Intervention\Image\Encoders\AvifEncoder;
|
||||
use Intervention\Image\Encoders\BmpEncoder;
|
||||
@ -50,6 +49,7 @@ use Intervention\Image\Interfaces\ModifierInterface;
|
||||
use Intervention\Image\Interfaces\ProfileInterface;
|
||||
use Intervention\Image\Interfaces\ResolutionInterface;
|
||||
use Intervention\Image\Interfaces\SizeInterface;
|
||||
use Intervention\Image\Modifiers\AlignRotationModifier;
|
||||
use Intervention\Image\Modifiers\BlendTransparencyModifier;
|
||||
use Intervention\Image\Modifiers\BlurModifier;
|
||||
use Intervention\Image\Modifiers\BrightnessModifier;
|
||||
@ -101,14 +101,6 @@ final class Image implements ImageInterface
|
||||
*/
|
||||
protected Origin $origin;
|
||||
|
||||
/**
|
||||
* Color is mixed with transparent areas when converting to a format which
|
||||
* does not support transparency.
|
||||
*
|
||||
* @var ColorInterface
|
||||
*/
|
||||
protected ColorInterface $blendingColor;
|
||||
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
@ -124,9 +116,6 @@ final class Image implements ImageInterface
|
||||
protected CollectionInterface $exif = new Collection()
|
||||
) {
|
||||
$this->origin = new Origin();
|
||||
$this->blendingColor = $this->colorspace()->importColor(
|
||||
new Color(255, 255, 255, 0)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -418,7 +407,9 @@ final class Image implements ImageInterface
|
||||
*/
|
||||
public function blendingColor(): ColorInterface
|
||||
{
|
||||
return $this->blendingColor;
|
||||
return $this->driver()->handleInput(
|
||||
$this->driver()->config()->blendingColor
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -428,7 +419,9 @@ final class Image implements ImageInterface
|
||||
*/
|
||||
public function setBlendingColor(mixed $color): ImageInterface
|
||||
{
|
||||
$this->blendingColor = $this->driver()->handleInput($color);
|
||||
$this->driver()->config()->setOptions(
|
||||
blendingColor: $this->driver()->handleInput($color)
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -603,6 +596,16 @@ final class Image implements ImageInterface
|
||||
return $this->modify(new RotateModifier($angle, $background));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ImageInterface::orient()
|
||||
*/
|
||||
public function orient(): ImageInterface
|
||||
{
|
||||
return $this->modify(new AlignRotationModifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
|
@ -8,6 +8,7 @@ use Intervention\Image\Interfaces\DriverInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Drivers\Gd\Driver as GdDriver;
|
||||
use Intervention\Image\Drivers\Imagick\Driver as ImagickDriver;
|
||||
use Intervention\Image\Exceptions\DriverException;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\ImageManagerInterface;
|
||||
|
||||
@ -18,10 +19,11 @@ final class ImageManager implements ImageManagerInterface
|
||||
/**
|
||||
* @link https://image.intervention.io/v3/basics/image-manager#create-a-new-image-manager-instance
|
||||
* @param string|DriverInterface $driver
|
||||
* @param mixed $options
|
||||
*/
|
||||
public function __construct(string|DriverInterface $driver)
|
||||
public function __construct(string|DriverInterface $driver, mixed ...$options)
|
||||
{
|
||||
$this->driver = $this->resolveDriver($driver);
|
||||
$this->driver = $this->resolveDriver($driver, ...$options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -29,33 +31,38 @@ final class ImageManager implements ImageManagerInterface
|
||||
*
|
||||
* @link https://image.intervention.io/v3/basics/image-manager
|
||||
* @param string|DriverInterface $driver
|
||||
* @param mixed $options
|
||||
* @return ImageManager
|
||||
*/
|
||||
public static function withDriver(string|DriverInterface $driver): self
|
||||
public static function withDriver(string|DriverInterface $driver, mixed ...$options): self
|
||||
{
|
||||
return new self(self::resolveDriver($driver));
|
||||
return new self(self::resolveDriver($driver, ...$options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create image manager with GD driver
|
||||
*
|
||||
* @link https://image.intervention.io/v3/basics/image-manager#static-gd-driver-constructor
|
||||
* @param mixed $options
|
||||
* @throws DriverException
|
||||
* @return ImageManager
|
||||
*/
|
||||
public static function gd(): self
|
||||
public static function gd(mixed ...$options): self
|
||||
{
|
||||
return self::withDriver(GdDriver::class);
|
||||
return self::withDriver(new GdDriver(), ...$options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create image manager with Imagick driver
|
||||
*
|
||||
* @link https://image.intervention.io/v3/basics/image-manager#static-imagick-driver-constructor
|
||||
* @param mixed $options
|
||||
* @throws DriverException
|
||||
* @return ImageManager
|
||||
*/
|
||||
public static function imagick(): self
|
||||
public static function imagick(mixed ...$options): self
|
||||
{
|
||||
return self::withDriver(ImagickDriver::class);
|
||||
return self::withDriver(new ImagickDriver(), ...$options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,14 +115,14 @@ final class ImageManager implements ImageManagerInterface
|
||||
* Return driver object
|
||||
*
|
||||
* @param string|DriverInterface $driver
|
||||
* @param mixed $options
|
||||
* @return DriverInterface
|
||||
*/
|
||||
private static function resolveDriver(string|DriverInterface $driver): DriverInterface
|
||||
private static function resolveDriver(string|DriverInterface $driver, mixed ...$options): DriverInterface
|
||||
{
|
||||
if (is_object($driver)) {
|
||||
return $driver;
|
||||
}
|
||||
$driver = is_string($driver) ? new $driver() : $driver;
|
||||
$driver->config()->setOptions(...$options);
|
||||
|
||||
return new $driver();
|
||||
return $driver;
|
||||
}
|
||||
}
|
||||
|
135
src/InputHandler.php
Normal file
135
src/InputHandler.php
Normal file
@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image;
|
||||
|
||||
use Intervention\Image\Colors\Cmyk\Decoders\StringColorDecoder as CmykStringColorDecoder;
|
||||
use Intervention\Image\Colors\Hsl\Decoders\StringColorDecoder as HslStringColorDecoder;
|
||||
use Intervention\Image\Colors\Hsv\Decoders\StringColorDecoder as HsvStringColorDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\HexColorDecoder as RgbHexColorDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\HtmlColornameDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\StringColorDecoder as RgbStringColorDecoder;
|
||||
use Intervention\Image\Colors\Rgb\Decoders\TransparentColorDecoder;
|
||||
use Intervention\Image\Decoders\Base64ImageDecoder;
|
||||
use Intervention\Image\Decoders\BinaryImageDecoder;
|
||||
use Intervention\Image\Decoders\ColorObjectDecoder;
|
||||
use Intervention\Image\Decoders\DataUriImageDecoder;
|
||||
use Intervention\Image\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Decoders\FilePointerImageDecoder;
|
||||
use Intervention\Image\Decoders\ImageObjectDecoder;
|
||||
use Intervention\Image\Decoders\NativeObjectDecoder;
|
||||
use Intervention\Image\Decoders\SplFileInfoImageDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Exceptions\DriverException;
|
||||
use Intervention\Image\Exceptions\NotSupportedException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\DecoderInterface;
|
||||
use Intervention\Image\Interfaces\DriverInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\InputHandlerInterface;
|
||||
|
||||
class InputHandler implements InputHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Decoder classnames in hierarchical order
|
||||
*
|
||||
* @var array<string|DecoderInterface>
|
||||
*/
|
||||
protected array $decoders = [
|
||||
NativeObjectDecoder::class,
|
||||
ImageObjectDecoder::class,
|
||||
ColorObjectDecoder::class,
|
||||
RgbHexColorDecoder::class,
|
||||
RgbStringColorDecoder::class,
|
||||
CmykStringColorDecoder::class,
|
||||
HsvStringColorDecoder::class,
|
||||
HslStringColorDecoder::class,
|
||||
TransparentColorDecoder::class,
|
||||
HtmlColornameDecoder::class,
|
||||
FilePointerImageDecoder::class,
|
||||
FilePathImageDecoder::class,
|
||||
SplFileInfoImageDecoder::class,
|
||||
BinaryImageDecoder::class,
|
||||
DataUriImageDecoder::class,
|
||||
Base64ImageDecoder::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Driver with which the decoder classes are specialized
|
||||
*
|
||||
* @var null|DriverInterface
|
||||
*/
|
||||
protected ?DriverInterface $driver = null;
|
||||
|
||||
/**
|
||||
* Create new input handler instance with given decoder classnames
|
||||
*
|
||||
* @param array<string|DecoderInterface> $decoders
|
||||
* @param DriverInterface $driver
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $decoders = [], ?DriverInterface $driver = null)
|
||||
{
|
||||
$this->decoders = count($decoders) ? $decoders : $this->decoders;
|
||||
$this->driver = $driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static factory method
|
||||
*
|
||||
* @param array<string|DecoderInterface> $decoders
|
||||
* @param null|DriverInterface $driver
|
||||
* @return InputHandler
|
||||
*/
|
||||
public static function withDecoders(array $decoders, ?DriverInterface $driver = null): self
|
||||
{
|
||||
return new self($decoders, $driver);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see InputHandlerInterface::handle()
|
||||
*/
|
||||
public function handle($input): ImageInterface|ColorInterface
|
||||
{
|
||||
foreach ($this->decoders as $decoder) {
|
||||
// resolve river specialized decoder
|
||||
$decoder = $this->resolve($decoder);
|
||||
|
||||
try {
|
||||
return $decoder->decode($input);
|
||||
} catch (DecoderException $e) {
|
||||
// let next decoder try
|
||||
}
|
||||
}
|
||||
|
||||
throw new DecoderException(isset($e) ? $e->getMessage() : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given classname to an decoder object
|
||||
*
|
||||
* @param string|DecoderInterface $decoder
|
||||
* @throws DriverException
|
||||
* @throws NotSupportedException
|
||||
* @return DecoderInterface
|
||||
*/
|
||||
private function resolve(string|DecoderInterface $decoder): DecoderInterface
|
||||
{
|
||||
if (($decoder instanceof DecoderInterface) && empty($this->driver)) {
|
||||
return $decoder;
|
||||
}
|
||||
|
||||
if (($decoder instanceof DecoderInterface) && !empty($this->driver)) {
|
||||
return $this->driver->specialize($decoder);
|
||||
}
|
||||
|
||||
if (empty($this->driver)) {
|
||||
return new $decoder();
|
||||
}
|
||||
|
||||
return $this->driver->specialize(new $decoder());
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Interfaces;
|
||||
|
||||
use Intervention\Image\Config;
|
||||
use Intervention\Image\Exceptions\DriverException;
|
||||
use Intervention\Image\Exceptions\NotSupportedException;
|
||||
use Intervention\Image\Exceptions\RuntimeException;
|
||||
@ -20,11 +21,19 @@ interface DriverInterface
|
||||
*/
|
||||
public function id(): string;
|
||||
|
||||
/**
|
||||
* Get driver configuration
|
||||
*
|
||||
* @return Config
|
||||
*/
|
||||
public function config(): Config;
|
||||
|
||||
/**
|
||||
* Resolve given object into a specialized version for the current driver
|
||||
*
|
||||
* @param ModifierInterface|AnalyzerInterface|EncoderInterface|DecoderInterface $object
|
||||
* @throws NotSupportedException
|
||||
* @throws DriverException
|
||||
* @return ModifierInterface|AnalyzerInterface|EncoderInterface|DecoderInterface
|
||||
*/
|
||||
public function specialize(
|
||||
@ -36,6 +45,7 @@ interface DriverInterface
|
||||
*
|
||||
* @param array<string|object> $objects
|
||||
* @throws NotSupportedException
|
||||
* @throws DriverException
|
||||
* @return array<object>
|
||||
*/
|
||||
public function specializeMultiple(array $objects): array;
|
||||
|
@ -247,7 +247,8 @@ interface ImageInterface extends IteratorAggregate, Countable
|
||||
* Return color that is mixed with transparent areas when converting to a format which
|
||||
* does not support transparency.
|
||||
*
|
||||
* @link https://image.intervention.io/v3/basics/colors#transparency
|
||||
* @deprecated Use configuration options of image manager instead
|
||||
* @throws RuntimeException
|
||||
* @return ColorInterface
|
||||
*/
|
||||
public function blendingColor(): ColorInterface;
|
||||
@ -256,7 +257,7 @@ interface ImageInterface extends IteratorAggregate, Countable
|
||||
* Set blending color will have no effect unless image is converted into a format
|
||||
* which does not support transparency.
|
||||
*
|
||||
* @link https://image.intervention.io/v3/basics/colors#transparency
|
||||
* @deprecated Use configuration options of image manager instead
|
||||
* @param mixed $color
|
||||
* @throws RuntimeException
|
||||
* @return ImageInterface
|
||||
@ -430,10 +431,19 @@ interface ImageInterface extends IteratorAggregate, Countable
|
||||
*/
|
||||
public function rotate(float $angle, mixed $background = 'ffffff'): self;
|
||||
|
||||
/**
|
||||
* Rotate the image to be upright according to exif information
|
||||
*
|
||||
* @link https://image.intervention.io/v3/modifying/effects#image-orientation-according-to-exif-data
|
||||
* @throws RuntimeException
|
||||
* @return ImageInterface
|
||||
*/
|
||||
public function orient(): self;
|
||||
|
||||
/**
|
||||
* Draw text on image
|
||||
*
|
||||
* @ink https://image.intervention.io/v3/modifying/text-fonts
|
||||
* @link https://image.intervention.io/v3/modifying/text-fonts
|
||||
* @param string $text
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Interfaces;
|
||||
|
||||
use Intervention\Image\Exceptions\DriverException;
|
||||
|
||||
interface SpecializableInterface
|
||||
{
|
||||
/**
|
||||
@ -18,6 +20,7 @@ interface SpecializableInterface
|
||||
* Set the driver for which the object is specialized
|
||||
*
|
||||
* @param DriverInterface $driver
|
||||
* @throws DriverException
|
||||
* @return SpecializableInterface
|
||||
*/
|
||||
public function setDriver(DriverInterface $driver): self;
|
||||
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Traits;
|
||||
|
||||
use Intervention\Image\Exceptions\DriverException;
|
||||
use Intervention\Image\Interfaces\DriverInterface;
|
||||
use Intervention\Image\Interfaces\SpecializableInterface;
|
||||
use ReflectionClass;
|
||||
@ -53,8 +54,30 @@ trait CanBeDriverSpecialized
|
||||
*/
|
||||
public function setDriver(DriverInterface $driver): SpecializableInterface
|
||||
{
|
||||
if (!$this->belongsToDriver($driver)) {
|
||||
throw new DriverException(
|
||||
"Class '" . $this::class . "' can not be used with " . $driver->id() . " driver."
|
||||
);
|
||||
}
|
||||
|
||||
$this->driver = $driver;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given object belongs to the driver's namespace
|
||||
*
|
||||
* @param object $object
|
||||
* @return bool
|
||||
*/
|
||||
protected function belongsToDriver(object $object): bool
|
||||
{
|
||||
$driverId = function (object $object): string|bool {
|
||||
$id = substr($object::class, 27);
|
||||
return strstr($id, "\\", true);
|
||||
};
|
||||
|
||||
return $driverId($this) === $driverId($object);
|
||||
}
|
||||
}
|
||||
|
@ -15,20 +15,20 @@ use PHPUnit\Framework\ExpectationFailedException;
|
||||
|
||||
abstract class BaseTestCase extends MockeryTestCase
|
||||
{
|
||||
public function getTestResourcePath($filename = 'test.jpg'): string
|
||||
public static function getTestResourcePath($filename = 'test.jpg'): string
|
||||
{
|
||||
return sprintf('%s/resources/%s', __DIR__, $filename);
|
||||
}
|
||||
|
||||
public function getTestResourceData($filename = 'test.jpg'): string
|
||||
public static function getTestResourceData($filename = 'test.jpg'): string
|
||||
{
|
||||
return file_get_contents($this->getTestResourcePath($filename));
|
||||
return file_get_contents(self::getTestResourcePath($filename));
|
||||
}
|
||||
|
||||
public function getTestResourcePointer($filename = 'test.jpg')
|
||||
{
|
||||
$pointer = fopen('php://temp', 'rw');
|
||||
fputs($pointer, $this->getTestResourceData($filename));
|
||||
fputs($pointer, self::getTestResourceData($filename));
|
||||
rewind($pointer);
|
||||
|
||||
return $pointer;
|
||||
|
@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests;
|
||||
|
||||
use Intervention\Image\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Core;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Drivers\Gd\Frame;
|
||||
use Intervention\Image\Image;
|
||||
@ -14,7 +14,7 @@ abstract class GdTestCase extends BaseTestCase
|
||||
{
|
||||
public function readTestImage($filename = 'test.jpg'): Image
|
||||
{
|
||||
return (new FilePathImageDecoder())->handle(
|
||||
return (new Driver())->specialize(new FilePathImageDecoder())->decode(
|
||||
$this->getTestResourcePath($filename)
|
||||
);
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ namespace Intervention\Image\Tests;
|
||||
|
||||
use Imagick;
|
||||
use ImagickPixel;
|
||||
use Intervention\Image\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Core;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
use Intervention\Image\Image;
|
||||
|
||||
@ -15,7 +15,7 @@ abstract class ImagickTestCase extends BaseTestCase
|
||||
{
|
||||
public function readTestImage($filename = 'test.jpg'): Image
|
||||
{
|
||||
return (new FilePathImageDecoder())->handle(
|
||||
return (new Driver())->specialize(new FilePathImageDecoder())->decode(
|
||||
$this->getTestResourcePath($filename)
|
||||
);
|
||||
}
|
||||
|
83
tests/Unit/ConfigTest.php
Normal file
83
tests/Unit/ConfigTest.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests\Unit;
|
||||
|
||||
use Intervention\Image\Config;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
|
||||
#[CoversClass(Config::class)]
|
||||
final class ConfigTest extends BaseTestCase
|
||||
{
|
||||
public function testConstructor(): void
|
||||
{
|
||||
$config = new Config();
|
||||
$this->assertInstanceOf(Config::class, $config);
|
||||
|
||||
$this->assertTrue($config->autoOrientation);
|
||||
$this->assertTrue($config->decodeAnimation);
|
||||
$this->assertEquals('ffffff', $config->blendingColor);
|
||||
|
||||
$config = new Config(
|
||||
autoOrientation: false,
|
||||
decodeAnimation: false,
|
||||
blendingColor: 'f00',
|
||||
);
|
||||
$this->assertInstanceOf(Config::class, $config);
|
||||
|
||||
$this->assertFalse($config->autoOrientation);
|
||||
$this->assertFalse($config->decodeAnimation);
|
||||
$this->assertEquals('f00', $config->blendingColor);
|
||||
}
|
||||
|
||||
public function testGetSetOptions(): void
|
||||
{
|
||||
$config = new Config();
|
||||
$this->assertTrue($config->autoOrientation);
|
||||
$this->assertTrue($config->decodeAnimation);
|
||||
$this->assertEquals('ffffff', $config->blendingColor);
|
||||
|
||||
$result = $config->setOptions(
|
||||
autoOrientation: false,
|
||||
decodeAnimation: false,
|
||||
blendingColor: 'f00',
|
||||
);
|
||||
|
||||
$this->assertFalse($config->autoOrientation);
|
||||
$this->assertFalse($config->decodeAnimation);
|
||||
$this->assertEquals('f00', $config->blendingColor);
|
||||
|
||||
$this->assertFalse($result->autoOrientation);
|
||||
$this->assertFalse($result->decodeAnimation);
|
||||
$this->assertEquals('f00', $result->blendingColor);
|
||||
|
||||
$result = $config->setOptions(blendingColor: '000');
|
||||
|
||||
$this->assertFalse($config->autoOrientation);
|
||||
$this->assertFalse($config->decodeAnimation);
|
||||
$this->assertEquals('000', $config->blendingColor);
|
||||
|
||||
$this->assertFalse($result->autoOrientation);
|
||||
$this->assertFalse($result->decodeAnimation);
|
||||
$this->assertEquals('000', $result->blendingColor);
|
||||
}
|
||||
|
||||
public function testSetOptionsWithArray(): void
|
||||
{
|
||||
$config = new Config();
|
||||
$result = $config->setOptions([
|
||||
'autoOrientation' => false,
|
||||
'decodeAnimation' => false,
|
||||
'blendingColor' => 'f00',
|
||||
]);
|
||||
|
||||
$this->assertFalse($config->autoOrientation);
|
||||
$this->assertFalse($config->decodeAnimation);
|
||||
$this->assertEquals('f00', $config->blendingColor);
|
||||
$this->assertFalse($result->autoOrientation);
|
||||
$this->assertFalse($result->decodeAnimation);
|
||||
$this->assertEquals('f00', $result->blendingColor);
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@ namespace Intervention\Image\Tests\Unit\Drivers;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use Exception;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\CollectionInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
@ -18,35 +17,6 @@ use stdClass;
|
||||
#[CoversClass(\Intervention\Image\Drivers\AbstractDecoder::class)]
|
||||
final class AbstractDecoderTest extends BaseTestCase
|
||||
{
|
||||
public function testHandle(): void
|
||||
{
|
||||
$result = Mockery::mock(ColorInterface::class);
|
||||
$decoder = Mockery::mock(AbstractDecoder::class);
|
||||
$decoder->shouldReceive('decode')->with('test input')->andReturn($result);
|
||||
$decoder->handle('test input');
|
||||
}
|
||||
|
||||
public function testHandleFail(): void
|
||||
{
|
||||
$decoder = Mockery::mock(AbstractDecoder::class, []);
|
||||
$decoder->shouldReceive('decode')->with('test input')->andThrow(DecoderException::class);
|
||||
$this->expectException(DecoderException::class);
|
||||
$decoder->handle('test input');
|
||||
}
|
||||
|
||||
public function testHandleFailWithSuccessor(): void
|
||||
{
|
||||
$result = Mockery::mock(ColorInterface::class);
|
||||
$successor = Mockery::mock(AbstractDecoder::class);
|
||||
$successor->shouldReceive('decode')->with('test input')->andReturn($result);
|
||||
$decoder = Mockery::mock(
|
||||
AbstractDecoder::class,
|
||||
[$successor]
|
||||
);
|
||||
$decoder->shouldReceive('decode')->with('test input')->andThrow(DecoderException::class);
|
||||
$decoder->handle('test input');
|
||||
}
|
||||
|
||||
public function testIsGifFormat(): void
|
||||
{
|
||||
$decoder = Mockery::mock(AbstractDecoder::class);
|
||||
|
@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests\Unit\Drivers;
|
||||
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use Intervention\Image\Drivers\AbstractDecoder;
|
||||
use Intervention\Image\Drivers\AbstractInputHandler;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
use Mockery;
|
||||
|
||||
#[CoversClass(\Intervention\Image\Drivers\AbstractInputHandler::class)]
|
||||
final class AbstractInputHandlerTest extends BaseTestCase
|
||||
{
|
||||
public function testHandle(): void
|
||||
{
|
||||
$image = Mockery::mock(ImageInterface::class);
|
||||
|
||||
$chain = Mockery::mock(AbstractDecoder::class);
|
||||
$chain->shouldReceive('handle')->with('test image')->andReturn($image);
|
||||
$chain->shouldReceive('decode')->with('test image')->andReturn(Mockery::mock(ImageInterface::class));
|
||||
|
||||
$modifier = $this->getModifier($chain);
|
||||
$modifier->handle('test image');
|
||||
}
|
||||
|
||||
public function testChainNoItems(): void
|
||||
{
|
||||
$handler = new class () extends AbstractInputHandler
|
||||
{
|
||||
};
|
||||
|
||||
$this->expectException(DecoderException::class);
|
||||
$handler->handle('test');
|
||||
}
|
||||
|
||||
private function getModifier(AbstractDecoder $chain): AbstractInputHandler
|
||||
{
|
||||
return new class ([$chain]) extends AbstractInputHandler
|
||||
{
|
||||
public function __construct(protected array $decoders = [])
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
protected function chain(): AbstractDecoder
|
||||
{
|
||||
return $this->decoders[0];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\Base64ImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
@ -20,6 +21,7 @@ final class Base64ImageDecoderTest extends BaseTestCase
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->decoder = new Base64ImageDecoder();
|
||||
$this->decoder->setDriver(new Driver());
|
||||
}
|
||||
|
||||
public function testDecode(): void
|
||||
|
@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\BinaryImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
|
||||
@ -14,10 +15,17 @@ use Intervention\Image\Tests\BaseTestCase;
|
||||
#[CoversClass(\Intervention\Image\Drivers\Gd\Decoders\BinaryImageDecoder::class)]
|
||||
final class BinaryImageDecoderTest extends BaseTestCase
|
||||
{
|
||||
protected BinaryImageDecoder $decoder;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->decoder = new BinaryImageDecoder();
|
||||
$this->decoder->setDriver(new Driver());
|
||||
}
|
||||
|
||||
public function testDecodePng(): void
|
||||
{
|
||||
$decoder = new BinaryImageDecoder();
|
||||
$image = $decoder->decode(file_get_contents($this->getTestResourcePath('tile.png')));
|
||||
$image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('tile.png')));
|
||||
$this->assertInstanceOf(Image::class, $image);
|
||||
$this->assertEquals(16, $image->width());
|
||||
$this->assertEquals(16, $image->height());
|
||||
@ -26,8 +34,7 @@ final class BinaryImageDecoderTest extends BaseTestCase
|
||||
|
||||
public function testDecodeGif(): void
|
||||
{
|
||||
$decoder = new BinaryImageDecoder();
|
||||
$image = $decoder->decode(file_get_contents($this->getTestResourcePath('red.gif')));
|
||||
$image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('red.gif')));
|
||||
$this->assertInstanceOf(Image::class, $image);
|
||||
$this->assertEquals(16, $image->width());
|
||||
$this->assertEquals(16, $image->height());
|
||||
@ -36,8 +43,7 @@ final class BinaryImageDecoderTest extends BaseTestCase
|
||||
|
||||
public function testDecodeAnimatedGif(): void
|
||||
{
|
||||
$decoder = new BinaryImageDecoder();
|
||||
$image = $decoder->decode(file_get_contents($this->getTestResourcePath('cats.gif')));
|
||||
$image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('cats.gif')));
|
||||
$this->assertInstanceOf(Image::class, $image);
|
||||
$this->assertEquals(75, $image->width());
|
||||
$this->assertEquals(50, $image->height());
|
||||
@ -46,8 +52,7 @@ final class BinaryImageDecoderTest extends BaseTestCase
|
||||
|
||||
public function testDecodeJpegWithExif(): void
|
||||
{
|
||||
$decoder = new BinaryImageDecoder();
|
||||
$image = $decoder->decode(file_get_contents($this->getTestResourcePath('exif.jpg')));
|
||||
$image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('exif.jpg')));
|
||||
$this->assertInstanceOf(Image::class, $image);
|
||||
$this->assertEquals(16, $image->width());
|
||||
$this->assertEquals(16, $image->height());
|
||||
|
@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\DataUriImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
@ -21,6 +22,7 @@ final class DataUriImageDecoderTest extends BaseTestCase
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->decoder = new DataUriImageDecoder();
|
||||
$this->decoder->setDriver(new Driver());
|
||||
}
|
||||
|
||||
public function testDecode(): void
|
||||
|
@ -7,10 +7,11 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
use stdClass;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
#[CoversClass(\Intervention\Image\Drivers\Gd\Decoders\FilePathImageDecoder::class)]
|
||||
@ -21,32 +22,35 @@ final class FilePathImageDecoderTest extends BaseTestCase
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->decoder = new FilePathImageDecoder();
|
||||
$this->decoder->setDriver(new Driver());
|
||||
}
|
||||
|
||||
public function testDecode(): void
|
||||
#[DataProvider('validFormatPathsProvider')]
|
||||
public function testDecode(string $path, bool $result): void
|
||||
{
|
||||
$result = $this->decoder->decode(
|
||||
$this->getTestResourcePath()
|
||||
);
|
||||
if ($result === false) {
|
||||
$this->expectException(DecoderException::class);
|
||||
}
|
||||
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
$result = $this->decoder->decode($path);
|
||||
|
||||
if ($result === true) {
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
}
|
||||
|
||||
public function testDecoderNonString(): void
|
||||
public static function validFormatPathsProvider(): array
|
||||
{
|
||||
$this->expectException(DecoderException::class);
|
||||
$this->decoder->decode(new stdClass());
|
||||
}
|
||||
|
||||
public function testDecoderNoPath(): void
|
||||
{
|
||||
$this->expectException(DecoderException::class);
|
||||
$this->decoder->decode('no-path');
|
||||
}
|
||||
|
||||
public function testDecoderTooLongPath(): void
|
||||
{
|
||||
$this->expectException(DecoderException::class);
|
||||
$this->decoder->decode(str_repeat('x', PHP_MAXPATHLEN + 1));
|
||||
return [
|
||||
[self::getTestResourcePath('cats.gif'), true],
|
||||
[self::getTestResourcePath('animation.gif'), true],
|
||||
[self::getTestResourcePath('red.gif'), true],
|
||||
[self::getTestResourcePath('green.gif'), true],
|
||||
[self::getTestResourcePath('blue.gif'), true],
|
||||
[self::getTestResourcePath('gradient.bmp'), true],
|
||||
[self::getTestResourcePath('circle.png'), true],
|
||||
['no-path', false],
|
||||
[str_repeat('x', PHP_MAXPATHLEN + 1), false],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\FilePointerImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\GdTestCase;
|
||||
|
||||
@ -17,6 +18,8 @@ final class FilePointerImageDecoderTest extends GdTestCase
|
||||
public function testDecode(): void
|
||||
{
|
||||
$decoder = new FilePointerImageDecoder();
|
||||
$decoder->setDriver(new Driver());
|
||||
|
||||
$fp = fopen($this->getTestResourcePath('test.jpg'), 'r');
|
||||
$result = $decoder->decode($fp);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
|
@ -6,12 +6,12 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders;
|
||||
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\ImageObjectDecoder;
|
||||
use Intervention\Image\Decoders\ImageObjectDecoder;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\GdTestCase;
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
#[CoversClass(\Intervention\Image\Drivers\Gd\Decoders\ImageObjectDecoder::class)]
|
||||
#[CoversClass(\Intervention\Image\Decoders\ImageObjectDecoder::class)]
|
||||
final class ImageObjectDecoderTest extends GdTestCase
|
||||
{
|
||||
public function testDecode(): void
|
||||
|
34
tests/Unit/Drivers/Gd/Decoders/NativeObjectDecoderTest.php
Normal file
34
tests/Unit/Drivers/Gd/Decoders/NativeObjectDecoderTest.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders;
|
||||
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\NativeObjectDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
#[CoversClass(NativeObjectDecoder::class)]
|
||||
final class NativeObjectDecoderTest extends BaseTestCase
|
||||
{
|
||||
protected NativeObjectDecoder $decoder;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->decoder = new NativeObjectDecoder();
|
||||
$this->decoder->setDriver(new Driver());
|
||||
}
|
||||
|
||||
public function testDecode(): void
|
||||
{
|
||||
$result = $this->decoder->decode(
|
||||
imagecreatetruecolor(3, 2)
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Gd\Decoders\SplFileInfoImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
use SplFileInfo;
|
||||
@ -18,6 +19,8 @@ final class SplFileInfoImageDecoderTest extends BaseTestCase
|
||||
public function testDecode(): void
|
||||
{
|
||||
$decoder = new SplFileInfoImageDecoder();
|
||||
$decoder->setDriver(new Driver());
|
||||
|
||||
$result = $decoder->decode(
|
||||
new SplFileInfo($this->getTestResourcePath('blue.gif'))
|
||||
);
|
||||
|
@ -7,7 +7,6 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd;
|
||||
use Intervention\Image\Analyzers\WidthAnalyzer;
|
||||
use Intervention\Image\Collection;
|
||||
use Intervention\Image\Colors\Hsl\Colorspace;
|
||||
use Intervention\Image\Colors\Rgb\Color;
|
||||
use Intervention\Image\Drivers\Gd\Core;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\Drivers\Gd\Frame;
|
||||
@ -280,17 +279,16 @@ final class ImageTest extends GdTestCase
|
||||
$this->assertInstanceOf(Image::class, $this->image->text('test', 0, 0, new Font()));
|
||||
}
|
||||
|
||||
public function testSetGetBlendingColor(): void
|
||||
public function testBlendTransparencyDefault(): void
|
||||
{
|
||||
$image = $this->readTestImage('gradient.gif');
|
||||
$this->assertInstanceOf(ColorInterface::class, $image->blendingColor());
|
||||
$this->assertColor(255, 255, 255, 0, $image->blendingColor());
|
||||
$result = $image->setBlendingColor(new Color(1, 2, 3, 4));
|
||||
$this->assertColor(1, 2, 3, 4, $result->blendingColor());
|
||||
$this->assertColor(1, 2, 3, 4, $image->blendingColor());
|
||||
$this->assertColor(0, 0, 0, 0, $image->pickColor(1, 0));
|
||||
$result = $image->blendTransparency();
|
||||
$this->assertColor(255, 255, 255, 255, $image->pickColor(1, 0));
|
||||
$this->assertColor(255, 255, 255, 255, $result->pickColor(1, 0));
|
||||
}
|
||||
|
||||
public function testBlendTransparency(): void
|
||||
public function testBlendTransparencyArgument(): void
|
||||
{
|
||||
$image = $this->readTestImage('gradient.gif');
|
||||
$this->assertColor(0, 0, 0, 0, $image->pickColor(1, 0));
|
||||
|
@ -1,153 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests\Unit\Drivers\Gd;
|
||||
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Colors\Cmyk\Color as CmykColor;
|
||||
use Intervention\Image\Colors\Hsv\Color as HsvColor;
|
||||
use Intervention\Image\Colors\Rgb\Color as RgbColor;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Drivers\Gd\InputHandler;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
use SplFileInfo;
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
#[CoversClass(\Intervention\Image\Drivers\Gd\InputHandler::class)]
|
||||
final class InputHandlerTest extends BaseTestCase
|
||||
{
|
||||
public function testHandleEmptyString(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$this->expectException(DecoderException::class);
|
||||
$handler->handle('');
|
||||
}
|
||||
|
||||
public function testHandleBinaryImage(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = file_get_contents($this->getTestResourcePath('test.jpg'));
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleGdImage(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$result = $handler->handle(imagecreatetruecolor(3, 2));
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleSplFileInfo(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = new SplFileInfo($this->getTestResourcePath('test.jpg'));
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleFilePathImage(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = $this->getTestResourcePath('animation.gif');
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleBase64Image(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = base64_encode(file_get_contents($this->getTestResourcePath('animation.gif')));
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleDataUriImage(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNb' .
|
||||
'yblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleHexColor(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = 'ccff33';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([204, 255, 51, 255], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$input = 'cf3';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([204, 255, 51, 255], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$input = '#123456';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([18, 52, 86, 255], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$input = '#333';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([51, 51, 51, 255], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$input = '#3333';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([51, 51, 51, 51], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$input = '#33333333';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([51, 51, 51, 51], $result->toArray());
|
||||
}
|
||||
|
||||
public function testHandleRgbString(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$result = $handler->handle('rgb(10, 20, 30)');
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([10, 20, 30, 255], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$result = $handler->handle('rgba(10, 20, 30, 1.0)');
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([10, 20, 30, 255], $result->toArray());
|
||||
}
|
||||
|
||||
public function testHandleHsvString(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$result = $handler->handle('hsv(10, 20, 30)');
|
||||
$this->assertInstanceOf(HsvColor::class, $result);
|
||||
$this->assertEquals([10, 20, 30], $result->toArray());
|
||||
}
|
||||
|
||||
public function testHandleCmykString(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$result = $handler->handle('cmyk(10, 20, 30, 40)');
|
||||
$this->assertInstanceOf(CmykColor::class, $result);
|
||||
$this->assertEquals([10, 20, 30, 40], $result->toArray());
|
||||
}
|
||||
|
||||
public function testHandleTransparent(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = 'transparent';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([255, 255, 255, 0], $result->toArray());
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests\Unit\Drivers\Gd\Traits;
|
||||
|
||||
use Intervention\Image\Drivers\Gd\Decoders\Traits\CanDecodeGif;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
use Mockery;
|
||||
|
||||
final class CanDecodeGifTest extends BaseTestCase
|
||||
{
|
||||
public function testDecodeGifFromBinaryAnimation(): void
|
||||
{
|
||||
$decoder = Mockery::mock(new class () {
|
||||
use CanDecodeGif;
|
||||
})->makePartial();
|
||||
|
||||
$result = $decoder->decodeGif($this->getTestResourceData('animation.gif'));
|
||||
$this->assertInstanceOf(ImageInterface::class, $result);
|
||||
$this->assertEquals('image/gif', $result->origin()->mediaType());
|
||||
}
|
||||
|
||||
public function testDecodeGifFromBinaryStatic(): void
|
||||
{
|
||||
$decoder = Mockery::mock(new class () {
|
||||
use CanDecodeGif;
|
||||
})->makePartial();
|
||||
|
||||
$result = $decoder->decodeGif($this->getTestResourceData('red.gif'));
|
||||
$this->assertInstanceOf(ImageInterface::class, $result);
|
||||
$this->assertEquals('image/gif', $result->origin()->mediaType());
|
||||
}
|
||||
|
||||
public function testDecodeGifFromPathAnimation(): void
|
||||
{
|
||||
$decoder = Mockery::mock(new class () {
|
||||
use CanDecodeGif;
|
||||
})->makePartial();
|
||||
|
||||
$result = $decoder->decodeGif($this->getTestResourcePath('animation.gif'));
|
||||
$this->assertInstanceOf(ImageInterface::class, $result);
|
||||
$this->assertEquals('image/gif', $result->origin()->mediaType());
|
||||
}
|
||||
|
||||
public function testDecodeGifFromPathStatic(): void
|
||||
{
|
||||
$decoder = Mockery::mock(new class () {
|
||||
use CanDecodeGif;
|
||||
})->makePartial();
|
||||
|
||||
$result = $decoder->decodeGif($this->getTestResourcePath('red.gif'));
|
||||
$this->assertInstanceOf(ImageInterface::class, $result);
|
||||
$this->assertEquals('image/gif', $result->origin()->mediaType());
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\Base64ImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
@ -20,6 +21,7 @@ final class Base64ImageDecoderTest extends BaseTestCase
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->decoder = new Base64ImageDecoder();
|
||||
$this->decoder->setDriver(new Driver());
|
||||
}
|
||||
|
||||
public function testDecode(): void
|
||||
|
@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders;
|
||||
use Intervention\Image\Colors\Cmyk\Colorspace as CmykColorspace;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\BinaryImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
@ -14,10 +15,17 @@ use stdClass;
|
||||
|
||||
final class BinaryImageDecoderTest extends BaseTestCase
|
||||
{
|
||||
protected BinaryImageDecoder $decoder;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->decoder = new BinaryImageDecoder();
|
||||
$this->decoder->setDriver(new Driver());
|
||||
}
|
||||
|
||||
public function testDecodePng(): void
|
||||
{
|
||||
$decoder = new BinaryImageDecoder();
|
||||
$image = $decoder->decode(file_get_contents($this->getTestResourcePath('tile.png')));
|
||||
$image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('tile.png')));
|
||||
$this->assertInstanceOf(Image::class, $image);
|
||||
$this->assertInstanceOf(RgbColorspace::class, $image->colorspace());
|
||||
$this->assertEquals(16, $image->width());
|
||||
@ -27,8 +35,7 @@ final class BinaryImageDecoderTest extends BaseTestCase
|
||||
|
||||
public function testDecodeGif(): void
|
||||
{
|
||||
$decoder = new BinaryImageDecoder();
|
||||
$image = $decoder->decode(file_get_contents($this->getTestResourcePath('red.gif')));
|
||||
$image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('red.gif')));
|
||||
$this->assertInstanceOf(Image::class, $image);
|
||||
$this->assertEquals(16, $image->width());
|
||||
$this->assertEquals(16, $image->height());
|
||||
@ -37,8 +44,7 @@ final class BinaryImageDecoderTest extends BaseTestCase
|
||||
|
||||
public function testDecodeAnimatedGif(): void
|
||||
{
|
||||
$decoder = new BinaryImageDecoder();
|
||||
$image = $decoder->decode(file_get_contents($this->getTestResourcePath('cats.gif')));
|
||||
$image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('cats.gif')));
|
||||
$this->assertInstanceOf(Image::class, $image);
|
||||
$this->assertEquals(75, $image->width());
|
||||
$this->assertEquals(50, $image->height());
|
||||
@ -47,8 +53,7 @@ final class BinaryImageDecoderTest extends BaseTestCase
|
||||
|
||||
public function testDecodeJpegWithExif(): void
|
||||
{
|
||||
$decoder = new BinaryImageDecoder();
|
||||
$image = $decoder->decode(file_get_contents($this->getTestResourcePath('exif.jpg')));
|
||||
$image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('exif.jpg')));
|
||||
$this->assertInstanceOf(Image::class, $image);
|
||||
$this->assertEquals(16, $image->width());
|
||||
$this->assertEquals(16, $image->height());
|
||||
@ -58,16 +63,14 @@ final class BinaryImageDecoderTest extends BaseTestCase
|
||||
|
||||
public function testDecodeCmykImage(): void
|
||||
{
|
||||
$decoder = new BinaryImageDecoder();
|
||||
$image = $decoder->decode(file_get_contents($this->getTestResourcePath('cmyk.jpg')));
|
||||
$image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('cmyk.jpg')));
|
||||
$this->assertInstanceOf(Image::class, $image);
|
||||
$this->assertInstanceOf(CmykColorspace::class, $image->colorspace());
|
||||
}
|
||||
|
||||
public function testDecodeNonString(): void
|
||||
{
|
||||
$decoder = new BinaryImageDecoder();
|
||||
$this->expectException(DecoderException::class);
|
||||
$decoder->decode(new stdClass());
|
||||
$this->decoder->decode(new stdClass());
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\DataUriImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
@ -21,6 +22,7 @@ final class DataUriImageDecoderTest extends BaseTestCase
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->decoder = new DataUriImageDecoder();
|
||||
$this->decoder->setDriver(new Driver());
|
||||
}
|
||||
|
||||
public function testDecode(): void
|
||||
|
@ -7,10 +7,11 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
use stdClass;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
#[CoversClass(\Intervention\Image\Drivers\Imagick\Decoders\FilePathImageDecoder::class)]
|
||||
@ -21,32 +22,35 @@ final class FilePathImageDecoderTest extends BaseTestCase
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->decoder = new FilePathImageDecoder();
|
||||
$this->decoder->setDriver(new Driver());
|
||||
}
|
||||
|
||||
public function testDecode(): void
|
||||
#[DataProvider('validFormatPathsProvider')]
|
||||
public function testDecode(string $path, bool $result): void
|
||||
{
|
||||
$result = $this->decoder->decode(
|
||||
$this->getTestResourcePath()
|
||||
);
|
||||
if ($result === false) {
|
||||
$this->expectException(DecoderException::class);
|
||||
}
|
||||
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
$result = $this->decoder->decode($path);
|
||||
|
||||
if ($result === true) {
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
}
|
||||
|
||||
public function testDecoderNonString(): void
|
||||
public static function validFormatPathsProvider(): array
|
||||
{
|
||||
$this->expectException(DecoderException::class);
|
||||
$this->decoder->decode(new stdClass());
|
||||
}
|
||||
|
||||
public function testDecoderNoPath(): void
|
||||
{
|
||||
$this->expectException(DecoderException::class);
|
||||
$this->decoder->decode('no-path');
|
||||
}
|
||||
|
||||
public function testDecoderTooLongPath(): void
|
||||
{
|
||||
$this->expectException(DecoderException::class);
|
||||
$this->decoder->decode(str_repeat('x', PHP_MAXPATHLEN + 1));
|
||||
return [
|
||||
[self::getTestResourcePath('cats.gif'), true],
|
||||
[self::getTestResourcePath('animation.gif'), true],
|
||||
[self::getTestResourcePath('red.gif'), true],
|
||||
[self::getTestResourcePath('green.gif'), true],
|
||||
[self::getTestResourcePath('blue.gif'), true],
|
||||
[self::getTestResourcePath('gradient.bmp'), true],
|
||||
[self::getTestResourcePath('circle.png'), true],
|
||||
['no-path', false],
|
||||
[str_repeat('x', PHP_MAXPATHLEN + 1), false],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\FilePointerImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\ImagickTestCase;
|
||||
|
||||
@ -17,6 +18,7 @@ final class FilePointerImageDecoderTest extends ImagickTestCase
|
||||
public function testDecode(): void
|
||||
{
|
||||
$decoder = new FilePointerImageDecoder();
|
||||
$decoder->setDriver(new Driver());
|
||||
$fp = fopen($this->getTestResourcePath('test.jpg'), 'r');
|
||||
$result = $decoder->decode($fp);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
|
@ -6,12 +6,12 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders;
|
||||
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\ImageObjectDecoder;
|
||||
use Intervention\Image\Decoders\ImageObjectDecoder;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\ImagickTestCase;
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
#[CoversClass(\Intervention\Image\Drivers\Imagick\Decoders\ImageObjectDecoder::class)]
|
||||
#[CoversClass(\Intervention\Image\Decoders\ImageObjectDecoder::class)]
|
||||
final class ImageObjectDecoderTest extends ImagickTestCase
|
||||
{
|
||||
public function testDecode(): void
|
||||
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders;
|
||||
|
||||
use Imagick;
|
||||
use ImagickPixel;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\NativeObjectDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
#[CoversClass(NativeObjectDecoder::class)]
|
||||
final class NativeObjectDecoderTest extends BaseTestCase
|
||||
{
|
||||
protected NativeObjectDecoder $decoder;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->decoder = new NativeObjectDecoder();
|
||||
$this->decoder->setDriver(new Driver());
|
||||
}
|
||||
|
||||
public function testDecode(): void
|
||||
{
|
||||
$native = new Imagick();
|
||||
$native->newImage(3, 2, new ImagickPixel('red'), 'png');
|
||||
$result = $this->decoder->decode($native);
|
||||
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Drivers\Imagick\Decoders\SplFileInfoImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
use SplFileInfo;
|
||||
@ -18,6 +19,7 @@ final class SplFileInfoImageDecoderTest extends BaseTestCase
|
||||
public function testDecode(): void
|
||||
{
|
||||
$decoder = new SplFileInfoImageDecoder();
|
||||
$decoder->setDriver(new Driver());
|
||||
$result = $decoder->decode(
|
||||
new SplFileInfo($this->getTestResourcePath('blue.gif'))
|
||||
);
|
||||
|
@ -8,7 +8,6 @@ use Imagick;
|
||||
use Intervention\Image\Analyzers\WidthAnalyzer;
|
||||
use Intervention\Image\Collection;
|
||||
use Intervention\Image\Colors\Cmyk\Colorspace as CmykColorspace;
|
||||
use Intervention\Image\Colors\Rgb\Color;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Drivers\Imagick\Core;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
@ -24,6 +23,7 @@ use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ResolutionInterface;
|
||||
use Intervention\Image\Interfaces\SizeInterface;
|
||||
use Intervention\Image\Modifiers\GreyscaleModifier;
|
||||
use Intervention\Image\Origin;
|
||||
use Intervention\Image\Tests\ImagickTestCase;
|
||||
|
||||
final class ImageTest extends ImagickTestCase
|
||||
@ -97,6 +97,16 @@ final class ImageTest extends ImagickTestCase
|
||||
$this->assertEquals(10, $this->image->loops());
|
||||
}
|
||||
|
||||
public function testSetGetOrigin(): void
|
||||
{
|
||||
$origin = $this->image->origin();
|
||||
$this->assertInstanceOf(Origin::class, $origin);
|
||||
$this->image->setOrigin(new Origin('test1', 'test2'));
|
||||
$this->assertInstanceOf(Origin::class, $this->image->origin());
|
||||
$this->assertEquals('test1', $this->image->origin()->mimetype());
|
||||
$this->assertEquals('test2', $this->image->origin()->filePath());
|
||||
}
|
||||
|
||||
public function testRemoveAnimation(): void
|
||||
{
|
||||
$this->assertTrue($this->image->isAnimated());
|
||||
@ -263,17 +273,16 @@ final class ImageTest extends ImagickTestCase
|
||||
$this->assertInstanceOf(Image::class, $this->image->sharpen(12));
|
||||
}
|
||||
|
||||
public function testSetGetBlendingColor(): void
|
||||
public function testBlendTransparencyDefault(): void
|
||||
{
|
||||
$image = $this->readTestImage('gradient.gif');
|
||||
$this->assertInstanceOf(ColorInterface::class, $image->blendingColor());
|
||||
$this->assertColor(255, 255, 255, 0, $image->blendingColor());
|
||||
$result = $image->setBlendingColor(new Color(1, 2, 3, 4));
|
||||
$this->assertColor(1, 2, 3, 4, $result->blendingColor());
|
||||
$this->assertColor(1, 2, 3, 4, $image->blendingColor());
|
||||
$this->assertColor(0, 0, 0, 0, $image->pickColor(1, 0));
|
||||
$result = $image->blendTransparency();
|
||||
$this->assertColor(255, 255, 255, 255, $image->pickColor(1, 0));
|
||||
$this->assertColor(255, 255, 255, 255, $result->pickColor(1, 0));
|
||||
}
|
||||
|
||||
public function testBlendTransparency(): void
|
||||
public function testBlendTransparencyArgument(): void
|
||||
{
|
||||
$image = $this->readTestImage('gradient.gif');
|
||||
$this->assertColor(0, 0, 0, 0, $image->pickColor(1, 0));
|
||||
|
@ -1,157 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests\Unit\Drivers\Imagick;
|
||||
|
||||
use Imagick;
|
||||
use ImagickPixel;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Colors\Cmyk\Color as CmykColor;
|
||||
use Intervention\Image\Colors\Hsv\Color as HsvColor;
|
||||
use Intervention\Image\Colors\Rgb\Color as RgbColor;
|
||||
use Intervention\Image\Drivers\Imagick\InputHandler;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\Image;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
use SplFileInfo;
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
#[CoversClass(\Intervention\Image\Drivers\Imagick\InputHandler::class)]
|
||||
final class InputHandlerTest extends BaseTestCase
|
||||
{
|
||||
public function testHandleEmptyString(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$this->expectException(DecoderException::class);
|
||||
$handler->handle('');
|
||||
}
|
||||
|
||||
public function testHandleBinaryImage(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = file_get_contents($this->getTestResourcePath('animation.gif'));
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleImagick(): void
|
||||
{
|
||||
$imagick = new Imagick();
|
||||
$imagick->newImage(3, 2, new ImagickPixel('rgba(255, 255, 255, 255)'), 'png');
|
||||
$handler = new InputHandler();
|
||||
$result = $handler->handle($imagick);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleSplFileInfo(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = new SplFileInfo($this->getTestResourcePath('test.jpg'));
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleFilePathImage(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = $this->getTestResourcePath('animation.gif');
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleBase64Image(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = base64_encode(file_get_contents($this->getTestResourcePath('animation.gif')));
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleDataUriImage(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACN' .
|
||||
'byblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(Image::class, $result);
|
||||
}
|
||||
|
||||
public function testHandleHexColor(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = 'ccff33';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([204, 255, 51, 255], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$input = 'cf3';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([204, 255, 51, 255], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$input = '#123456';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([18, 52, 86, 255], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$input = '#333';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([51, 51, 51, 255], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$input = '#3333';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([51, 51, 51, 51], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$input = '#33333333';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([51, 51, 51, 51], $result->toArray());
|
||||
}
|
||||
|
||||
public function testHandleRgbString(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$result = $handler->handle('rgb(10, 20, 30)');
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([10, 20, 30, 255], $result->toArray());
|
||||
|
||||
$handler = new InputHandler();
|
||||
$result = $handler->handle('rgba(10, 20, 30, 1.0)');
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([10, 20, 30, 255], $result->toArray());
|
||||
}
|
||||
|
||||
public function testHandleCmykString(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$result = $handler->handle('cmyk(10, 20, 30, 40)');
|
||||
$this->assertInstanceOf(CmykColor::class, $result);
|
||||
$this->assertEquals([10, 20, 30, 40], $result->toArray());
|
||||
}
|
||||
|
||||
public function testHandleHsvString(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$result = $handler->handle('hsv(10, 20, 30)');
|
||||
$this->assertInstanceOf(HsvColor::class, $result);
|
||||
$this->assertEquals([10, 20, 30], $result->toArray());
|
||||
}
|
||||
|
||||
public function testHandleTransparent(): void
|
||||
{
|
||||
$handler = new InputHandler();
|
||||
$input = 'transparent';
|
||||
$result = $handler->handle($input);
|
||||
$this->assertInstanceOf(RgbColor::class, $result);
|
||||
$this->assertEquals([255, 255, 255, 0], $result->toArray());
|
||||
}
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests\Unit;
|
||||
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Decoders\BinaryImageDecoder;
|
||||
use Intervention\Image\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Driver as GdDriver;
|
||||
use Intervention\Image\Drivers\Imagick\Driver as ImagickDriver;
|
||||
use Intervention\Image\ImageManager;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
|
||||
#[CoversClass(\Intervention\Image\ImageManager::class)]
|
||||
final class ImageManagerTest extends BaseTestCase
|
||||
{
|
||||
public function testConstructor(): void
|
||||
{
|
||||
$manager = new ImageManager(new GdDriver());
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
|
||||
$manager = new ImageManager(GdDriver::class);
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
}
|
||||
|
||||
public function testWithDriver(): void
|
||||
{
|
||||
$manager = ImageManager::withDriver(new GdDriver());
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
|
||||
$manager = ImageManager::withDriver(GdDriver::class);
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
}
|
||||
|
||||
public function testDriver(): void
|
||||
{
|
||||
$driver = new GdDriver();
|
||||
$manager = ImageManager::withDriver($driver);
|
||||
$this->assertEquals($driver, $manager->driver());
|
||||
}
|
||||
|
||||
public function testDriverStatics(): void
|
||||
{
|
||||
$manager = ImageManager::gd();
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
|
||||
$manager = ImageManager::imagick();
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
public function testCreateGd(): void
|
||||
{
|
||||
$manager = new ImageManager(GdDriver::class);
|
||||
$image = $manager->create(5, 4);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
public function testAnimateGd(): void
|
||||
{
|
||||
$manager = new ImageManager(GdDriver::class);
|
||||
$image = $manager->animate(function ($animation) {
|
||||
$animation->add($this->getTestResourcePath('red.gif'), .25);
|
||||
});
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
public function testReadGd(): void
|
||||
{
|
||||
$manager = new ImageManager(GdDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'));
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
public function testReadGdWithDecoderClassname(): void
|
||||
{
|
||||
$manager = new ImageManager(GdDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), FilePathImageDecoder::class);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
public function testReadGdWithDecoderInstance(): void
|
||||
{
|
||||
$manager = new ImageManager(GdDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), new FilePathImageDecoder());
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
public function testReadGdWithDecoderClassnameArray(): void
|
||||
{
|
||||
$manager = new ImageManager(GdDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [FilePathImageDecoder::class]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
public function testReadGdWithDecoderInstanceArray(): void
|
||||
{
|
||||
$manager = new ImageManager(GdDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [new FilePathImageDecoder()]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
public function testReadGdWithDecoderInstanceArrayMultiple(): void
|
||||
{
|
||||
$manager = new ImageManager(GdDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [
|
||||
new BinaryImageDecoder(),
|
||||
new FilePathImageDecoder(),
|
||||
]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
public function testReadGdWithRotationAdjustment(): void
|
||||
{
|
||||
$manager = new ImageManager(GdDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('orientation.jpg'));
|
||||
$this->assertColor(255, 255, 255, 255, $image->pickColor(0, 24));
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
public function testCreateImagick(): void
|
||||
{
|
||||
$manager = new ImageManager(ImagickDriver::class);
|
||||
$image = $manager->create(5, 4);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
public function testAnimateImagick(): void
|
||||
{
|
||||
$manager = new ImageManager(ImagickDriver::class);
|
||||
$image = $manager->animate(function ($animation) {
|
||||
$animation->add($this->getTestResourcePath('red.gif'), .25);
|
||||
});
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
public function testReadImagick(): void
|
||||
{
|
||||
$manager = new ImageManager(ImagickDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'));
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
public function testReadImagickWithDecoderClassname(): void
|
||||
{
|
||||
$manager = new ImageManager(ImagickDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), FilePathImageDecoder::class);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
public function testReadImagickWithDecoderInstance(): void
|
||||
{
|
||||
$manager = new ImageManager(ImagickDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), new FilePathImageDecoder());
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
public function testReadImagickWithDecoderClassnameArray(): void
|
||||
{
|
||||
$manager = new ImageManager(ImagickDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [FilePathImageDecoder::class]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
public function testReadImagickWithDecoderInstanceArray(): void
|
||||
{
|
||||
$manager = new ImageManager(ImagickDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [new FilePathImageDecoder()]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
public function testReadImagickWithDecoderInstanceArrayMultiple(): void
|
||||
{
|
||||
$manager = new ImageManager(ImagickDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [
|
||||
new BinaryImageDecoder(),
|
||||
new FilePathImageDecoder(),
|
||||
]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
public function testReadImagickWithRotationAdjustment(): void
|
||||
{
|
||||
$manager = new ImageManager(ImagickDriver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('orientation.jpg'));
|
||||
$this->assertColor(255, 255, 255, 255, $image->pickColor(0, 24));
|
||||
}
|
||||
}
|
157
tests/Unit/ImageManagerTestGd.php
Normal file
157
tests/Unit/ImageManagerTestGd.php
Normal file
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests\Unit;
|
||||
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Decoders\BinaryImageDecoder;
|
||||
use Intervention\Image\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Driver;
|
||||
use Intervention\Image\ImageManager;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
|
||||
#[CoversClass(ImageManager::class)]
|
||||
#[RequiresPhpExtension('gd')]
|
||||
final class ImageManagerTestGd extends BaseTestCase
|
||||
{
|
||||
public function testConstructor(): void
|
||||
{
|
||||
$manager = new ImageManager(new Driver());
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
}
|
||||
|
||||
public function testWithDriver(): void
|
||||
{
|
||||
$manager = ImageManager::withDriver(new Driver());
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
|
||||
$manager = ImageManager::withDriver(Driver::class);
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
}
|
||||
|
||||
public function testDriver(): void
|
||||
{
|
||||
$driver = new Driver();
|
||||
$manager = ImageManager::withDriver($driver);
|
||||
$this->assertEquals($driver, $manager->driver());
|
||||
}
|
||||
|
||||
public function testDriverStatic(): void
|
||||
{
|
||||
$manager = ImageManager::gd();
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
}
|
||||
|
||||
public function testCreate(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->create(5, 4);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testAnimate(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->animate(function ($animation) {
|
||||
$animation->add($this->getTestResourcePath('red.gif'), .25);
|
||||
});
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testRead(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'));
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithDecoderClassname(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), FilePathImageDecoder::class);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithDecoderInstance(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), new FilePathImageDecoder());
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithDecoderClassnameArray(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [FilePathImageDecoder::class]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithDecoderInstanceArray(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [new FilePathImageDecoder()]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithDecoderInstanceArrayMultiple(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [
|
||||
new BinaryImageDecoder(),
|
||||
new FilePathImageDecoder(),
|
||||
]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithRotationAdjustment(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('orientation.jpg'));
|
||||
$this->assertColor(1, 0, 254, 255, $image->pickColor(3, 3));
|
||||
}
|
||||
|
||||
public function testReadWithoutRotationAdjustment(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class, autoOrientation: false);
|
||||
$image = $manager->read($this->getTestResourcePath('orientation.jpg'));
|
||||
$this->assertColor(250, 2, 3, 255, $image->pickColor(3, 3));
|
||||
}
|
||||
|
||||
public function testReadAnimation(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('animation.gif'));
|
||||
$this->assertTrue($image->isAnimated());
|
||||
}
|
||||
|
||||
public function testReadAnimationDiscarded(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class, decodeAnimation: false);
|
||||
$image = $manager->read($this->getTestResourcePath('animation.gif'));
|
||||
$this->assertFalse($image->isAnimated());
|
||||
}
|
||||
|
||||
public function testApplyBlendingColorDefault(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('blocks.png'));
|
||||
$result = $image->blendTransparency();
|
||||
$this->assertColor(255, 255, 255, 255, $image->pickColor(530, 0));
|
||||
$this->assertColor(255, 255, 255, 255, $result->pickColor(530, 0));
|
||||
}
|
||||
|
||||
public function testApplyBlendingColorConfigured(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class, blendingColor: 'ff5500');
|
||||
$image = $manager->read($this->getTestResourcePath('blocks.png'));
|
||||
$result = $image->blendTransparency();
|
||||
$this->assertColor(255, 85, 0, 255, $image->pickColor(530, 0));
|
||||
$this->assertColor(255, 85, 0, 255, $result->pickColor(530, 0));
|
||||
}
|
||||
}
|
157
tests/Unit/ImageManagerTestImagick.php
Normal file
157
tests/Unit/ImageManagerTestImagick.php
Normal file
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests\Unit;
|
||||
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use Intervention\Image\Decoders\BinaryImageDecoder;
|
||||
use Intervention\Image\Decoders\FilePathImageDecoder;
|
||||
use Intervention\Image\Drivers\Imagick\Driver;
|
||||
use Intervention\Image\ImageManager;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
|
||||
#[CoversClass(ImageManager::class)]
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
final class ImageManagerTestImagick extends BaseTestCase
|
||||
{
|
||||
public function testConstructor(): void
|
||||
{
|
||||
$manager = new ImageManager(new Driver());
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
}
|
||||
|
||||
public function testWithDriver(): void
|
||||
{
|
||||
$manager = ImageManager::withDriver(new Driver());
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
|
||||
$manager = ImageManager::withDriver(Driver::class);
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
}
|
||||
|
||||
public function testDriver(): void
|
||||
{
|
||||
$driver = new Driver();
|
||||
$manager = ImageManager::withDriver($driver);
|
||||
$this->assertEquals($driver, $manager->driver());
|
||||
}
|
||||
|
||||
public function testDriverStatic(): void
|
||||
{
|
||||
$manager = ImageManager::imagick();
|
||||
$this->assertInstanceOf(ImageManager::class, $manager);
|
||||
}
|
||||
|
||||
public function testCreate(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->create(5, 4);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testAnimate(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->animate(function ($animation) {
|
||||
$animation->add($this->getTestResourcePath('red.gif'), .25);
|
||||
});
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testRead(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'));
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithDecoderClassname(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), FilePathImageDecoder::class);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithDecoderInstance(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), new FilePathImageDecoder());
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithDecoderClassnameArray(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [FilePathImageDecoder::class]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithDecoderInstanceArray(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [new FilePathImageDecoder()]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithDecoderInstanceArrayMultiple(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('red.gif'), [
|
||||
new BinaryImageDecoder(),
|
||||
new FilePathImageDecoder(),
|
||||
]);
|
||||
$this->assertInstanceOf(ImageInterface::class, $image);
|
||||
}
|
||||
|
||||
public function testReadWithRotationAdjustment(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('orientation.jpg'));
|
||||
$this->assertColor(1, 0, 254, 255, $image->pickColor(3, 3));
|
||||
}
|
||||
|
||||
public function testReadWithoutRotationAdjustment(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class, autoOrientation: false);
|
||||
$image = $manager->read($this->getTestResourcePath('orientation.jpg'));
|
||||
$this->assertColor(250, 2, 3, 255, $image->pickColor(3, 3));
|
||||
}
|
||||
|
||||
public function testReadAnimation(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('animation.gif'));
|
||||
$this->assertTrue($image->isAnimated());
|
||||
}
|
||||
|
||||
public function testReadAnimationDiscarded(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class, decodeAnimation: false);
|
||||
$image = $manager->read($this->getTestResourcePath('animation.gif'));
|
||||
$this->assertFalse($image->isAnimated());
|
||||
}
|
||||
|
||||
public function testApplyBlendingColor(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class);
|
||||
$image = $manager->read($this->getTestResourcePath('blocks.png'));
|
||||
$result = $image->blendTransparency();
|
||||
$this->assertColor(255, 255, 255, 255, $image->pickColor(530, 0));
|
||||
$this->assertColor(255, 255, 255, 255, $result->pickColor(530, 0));
|
||||
}
|
||||
|
||||
public function testApplyBlendingColorConfigured(): void
|
||||
{
|
||||
$manager = new ImageManager(Driver::class, blendingColor: 'ff5500');
|
||||
$image = $manager->read($this->getTestResourcePath('blocks.png'));
|
||||
$result = $image->blendTransparency();
|
||||
$this->assertColor(255, 85, 0, 255, $image->pickColor(530, 0));
|
||||
$this->assertColor(255, 85, 0, 255, $result->pickColor(530, 0));
|
||||
}
|
||||
}
|
74
tests/Unit/InputHandlerTest.php
Normal file
74
tests/Unit/InputHandlerTest.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Tests\Unit;
|
||||
|
||||
use Intervention\Image\Colors\Rgb\Decoders\HexColorDecoder;
|
||||
use Intervention\Image\Drivers\Gd\Driver as GdDriver;
|
||||
use Intervention\Image\Drivers\Imagick\Driver as ImagickDriver;
|
||||
use Intervention\Image\Exceptions\DecoderException;
|
||||
use Intervention\Image\InputHandler;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Tests\BaseTestCase;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
|
||||
#[RequiresPhpExtension('gd')]
|
||||
#[RequiresPhpExtension('imagick')]
|
||||
#[CoversClass(InputHandler::class)]
|
||||
class InputHandlerTest extends BaseTestCase
|
||||
{
|
||||
#[DataProvider('testHandleProvider')]
|
||||
public function testHandleDefaultDecoders(string $driver, mixed $input, string $outputClassname): void
|
||||
{
|
||||
$handler = new InputHandler(driver: new $driver());
|
||||
if ($outputClassname === ImageInterface::class || $outputClassname === ColorInterface::class) {
|
||||
$this->assertInstanceOf($outputClassname, $handler->handle($input));
|
||||
} else {
|
||||
$this->expectException($outputClassname);
|
||||
$handler->handle($input);
|
||||
}
|
||||
}
|
||||
|
||||
public static function testHandleProvider(): array
|
||||
{
|
||||
$base = [
|
||||
[null, DecoderException::class],
|
||||
['', DecoderException::class],
|
||||
['fff', ColorInterface::class],
|
||||
['rgba(0, 0, 0, 0)', ColorInterface::class],
|
||||
['cmyk(0, 0, 0, 0)', ColorInterface::class],
|
||||
['hsv(0, 0, 0)', ColorInterface::class],
|
||||
['hsl(0, 0, 0)', ColorInterface::class],
|
||||
['transparent', ColorInterface::class],
|
||||
['steelblue', ColorInterface::class],
|
||||
[self::getTestResourcePath(), ImageInterface::class],
|
||||
[file_get_contents(self::getTestResourcePath()), ImageInterface::class],
|
||||
];
|
||||
|
||||
$data = [];
|
||||
$drivers = [GdDriver::class, ImagickDriver::class];
|
||||
foreach ($drivers as $driver) {
|
||||
foreach ($base as $line) {
|
||||
array_unshift($line, $driver); // prepend driver
|
||||
$data[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function testResolveWithoutDriver(): void
|
||||
{
|
||||
$handler = new InputHandler([new HexColorDecoder()]);
|
||||
$result = $handler->handle('fff');
|
||||
$this->assertInstanceOf(ColorInterface::class, $result);
|
||||
|
||||
$handler = new InputHandler([HexColorDecoder::class]);
|
||||
$result = $handler->handle('fff');
|
||||
$this->assertInstanceOf(ColorInterface::class, $result);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user