1
0
mirror of https://github.com/Intervention/image.git synced 2025-01-17 12:18:14 +01:00

Add tests, improve code

This commit is contained in:
Oliver Vogel 2024-05-10 16:30:22 +02:00
parent 3ad426153a
commit 64632cd2c3
No known key found for this signature in database
GPG Key ID: 1B19D214C02D69BB
18 changed files with 150 additions and 108 deletions

View File

@ -9,10 +9,6 @@ use Intervention\Image\Interfaces\ConfigInterface;
class Config implements ConfigInterface
{
public const AUTO_ORIENTATION = 'autoOrientation';
public const DECODE_ANIMATION = 'decodeAnimation';
public const BLENDING_COLOR = 'blendingColor';
/**
* Create config object instance
*
@ -22,26 +18,12 @@ class Config implements ConfigInterface
* @return void
*/
public function __construct(
protected bool $autoOrientation = true,
protected bool $decodeAnimation = true,
protected mixed $blendingColor = 'ffffff00',
public bool $autoOrientation = true,
public bool $decodeAnimation = true,
public mixed $blendingColor = 'ffffff',
) {
}
/**
* {@inheritdoc}
*
* @see ConfigInterface::option()
*/
public function option(string $name, mixed $default = null): mixed
{
if (!property_exists($this, $name)) {
return $default;
}
return $this->{$name};
}
/**
* {@inheritdoc}
*

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Intervention\Image\Drivers\Gd\Decoders;
use Intervention\Image\Config;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\DecoderInterface;
@ -61,7 +60,7 @@ class BinaryImageDecoder extends NativeObjectDecoder implements DecoderInterface
}
// adjust image orientation
if ($this->driver()->config()->option(Config::AUTO_ORIENTATION) === true) {
if ($this->driver()->config()->autoOrientation === true) {
$image->modify(new AlignRotationModifier());
}

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Intervention\Image\Drivers\Gd\Decoders;
use Intervention\Image\Config;
use Intervention\Image\Exceptions\DecoderException;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\DecoderInterface;
@ -51,7 +50,7 @@ class FilePathImageDecoder extends NativeObjectDecoder implements DecoderInterfa
$image->setExif($this->extractExifData($input));
// adjust image orientation
if ($this->driver()->config()->option(Config::AUTO_ORIENTATION) === true) {
if ($this->driver()->config()->autoOrientation === true) {
$image->modify(new AlignRotationModifier());
}

View File

@ -7,7 +7,6 @@ namespace Intervention\Image\Drivers\Gd\Decoders;
use GdImage;
use Intervention\Gif\Decoder as GifDecoder;
use Intervention\Gif\Splitter as GifSplitter;
use Intervention\Image\Config;
use Intervention\Image\Drivers\Gd\Core;
use Intervention\Image\Drivers\Gd\Frame;
use Intervention\Image\Exceptions\DecoderException;
@ -61,7 +60,7 @@ class NativeObjectDecoder extends AbstractDecoder
protected function decodeGif(mixed $input): ImageInterface
{
// create non-animated image depending on config
if (!$this->driver()->config()->option(Config::DECODE_ANIMATION) === true) {
if (!$this->driver()->config()->decodeAnimation === true) {
$native = match (true) {
$this->isGifFormat($input) => @imagecreatefromstring($input),
default => @imagecreatefromgif($input),

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Intervention\Image\Drivers\Imagick\Decoders;
use Imagick;
use Intervention\Image\Config;
use Intervention\Image\Drivers\Imagick\Core;
use Intervention\Image\Drivers\SpecializableDecoder;
use Intervention\Image\Exceptions\DecoderException;
@ -41,12 +40,12 @@ class NativeObjectDecoder extends SpecializableDecoder
);
// discard animation depending on config
if (!$this->driver()->config()->option(Config::DECODE_ANIMATION) === true) {
if (!$this->driver()->config()->decodeAnimation === true) {
$image->modify(new RemoveAnimationModifier());
}
// adjust image rotatation
if ($this->driver()->config()->option(Config::AUTO_ORIENTATION) === true) {
if ($this->driver()->config()->autoOrientation === true) {
$image->modify(new AlignRotationModifier());
}

View File

@ -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

View File

@ -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

View File

@ -408,7 +408,7 @@ final class Image implements ImageInterface
public function blendingColor(): ColorInterface
{
return $this->driver()->handleInput(
$this->driver()->config()->option(Config::BLENDING_COLOR)
$this->driver()->config()->blendingColor
);
}
@ -419,9 +419,8 @@ final class Image implements ImageInterface
*/
public function setBlendingColor(mixed $color): ImageInterface
{
$this->driver()->config()->setOption(
Config::BLENDING_COLOR,
$this->driver()->handleInput($color)
$this->driver()->config()->setOptions(
blendingColor: $this->driver()->handleInput($color)
);
return $this;

View File

@ -8,14 +8,6 @@ use Intervention\Image\Exceptions\InputException;
interface ConfigInterface
{
/**
* Return value of given config option
*
* @param string $name
* @return mixed
*/
public function option(string $name, mixed $default = null): mixed;
/**
* Set value of given config option
*

View File

@ -16,9 +16,9 @@ final class ConfigTest extends BaseTestCase
$config = new Config();
$this->assertInstanceOf(Config::class, $config);
$this->assertTrue($config->option('autoOrientation'));
$this->assertTrue($config->option('decodeAnimation'));
$this->assertEquals('ffffff00', $config->option('blendingColor'));
$this->assertTrue($config->autoOrientation);
$this->assertTrue($config->decodeAnimation);
$this->assertEquals('ffffff', $config->blendingColor);
$config = new Config(
autoOrientation: false,
@ -27,17 +27,17 @@ final class ConfigTest extends BaseTestCase
);
$this->assertInstanceOf(Config::class, $config);
$this->assertFalse($config->option('autoOrientation'));
$this->assertFalse($config->option('decodeAnimation'));
$this->assertEquals('f00', $config->option('blendingColor'));
$this->assertFalse($config->autoOrientation);
$this->assertFalse($config->decodeAnimation);
$this->assertEquals('f00', $config->blendingColor);
}
public function testGetSetOptions(): void
{
$config = new Config();
$this->assertTrue($config->option('autoOrientation'));
$this->assertTrue($config->option('decodeAnimation'));
$this->assertEquals('ffffff00', $config->option('blendingColor'));
$this->assertTrue($config->autoOrientation);
$this->assertTrue($config->decodeAnimation);
$this->assertEquals('ffffff', $config->blendingColor);
$result = $config->setOptions(
autoOrientation: false,
@ -45,25 +45,22 @@ final class ConfigTest extends BaseTestCase
blendingColor: 'f00',
);
$this->assertFalse($config->option('autoOrientation'));
$this->assertFalse($config->option('decodeAnimation'));
$this->assertEquals('f00', $config->option('blendingColor'));
$this->assertFalse($config->autoOrientation);
$this->assertFalse($config->decodeAnimation);
$this->assertEquals('f00', $config->blendingColor);
$this->assertFalse($result->option('autoOrientation'));
$this->assertFalse($result->option('decodeAnimation'));
$this->assertEquals('f00', $result->option('blendingColor'));
$this->assertFalse($result->autoOrientation);
$this->assertFalse($result->decodeAnimation);
$this->assertEquals('f00', $result->blendingColor);
$result = $config->setOption('blendingColor', '000');
$this->assertFalse($config->option('autoOrientation'));
$this->assertFalse($config->option('decodeAnimation'));
$this->assertEquals('000', $config->option('blendingColor'));
$this->assertFalse($config->autoOrientation);
$this->assertFalse($config->decodeAnimation);
$this->assertEquals('000', $config->blendingColor);
$this->assertFalse($result->option('autoOrientation'));
$this->assertFalse($result->option('decodeAnimation'));
$this->assertEquals('000', $result->option('blendingColor'));
$this->assertNull($config->option('unknown'));
$this->assertEquals('test', $config->option('unknown', 'test'));
$this->assertFalse($result->autoOrientation);
$this->assertFalse($result->decodeAnimation);
$this->assertEquals('000', $result->blendingColor);
}
}

View File

@ -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));

View File

@ -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;
@ -263,17 +262,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));

View File

@ -48,14 +48,14 @@ final class ImageManagerTestGd extends BaseTestCase
$this->assertInstanceOf(ImageManager::class, $manager);
}
public function testCreateGd(): void
public function testCreate(): void
{
$manager = new ImageManager(Driver::class);
$image = $manager->create(5, 4);
$this->assertInstanceOf(ImageInterface::class, $image);
}
public function testAnimateGd(): void
public function testAnimate(): void
{
$manager = new ImageManager(Driver::class);
$image = $manager->animate(function ($animation) {
@ -64,42 +64,42 @@ final class ImageManagerTestGd extends BaseTestCase
$this->assertInstanceOf(ImageInterface::class, $image);
}
public function testReadGd(): void
public function testRead(): void
{
$manager = new ImageManager(Driver::class);
$image = $manager->read($this->getTestResourcePath('red.gif'));
$this->assertInstanceOf(ImageInterface::class, $image);
}
public function testReadGdWithDecoderClassname(): void
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 testReadGdWithDecoderInstance(): void
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 testReadGdWithDecoderClassnameArray(): void
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 testReadGdWithDecoderInstanceArray(): void
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 testReadGdWithDecoderInstanceArrayMultiple(): void
public function testReadWithDecoderInstanceArrayMultiple(): void
{
$manager = new ImageManager(Driver::class);
$image = $manager->read($this->getTestResourcePath('red.gif'), [
@ -109,17 +109,49 @@ final class ImageManagerTestGd extends BaseTestCase
$this->assertInstanceOf(ImageInterface::class, $image);
}
public function testReadGdWithRotationAdjustment(): void
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 testReadImagickWithoutRotationAdjustment(): void
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));
}
}

View File

@ -48,14 +48,14 @@ final class ImageManagerTestImagick extends BaseTestCase
$this->assertInstanceOf(ImageManager::class, $manager);
}
public function testCreateImagick(): void
public function testCreate(): void
{
$manager = new ImageManager(Driver::class);
$image = $manager->create(5, 4);
$this->assertInstanceOf(ImageInterface::class, $image);
}
public function testAnimateImagick(): void
public function testAnimate(): void
{
$manager = new ImageManager(Driver::class);
$image = $manager->animate(function ($animation) {
@ -64,42 +64,42 @@ final class ImageManagerTestImagick extends BaseTestCase
$this->assertInstanceOf(ImageInterface::class, $image);
}
public function testReadImagick(): void
public function testRead(): void
{
$manager = new ImageManager(Driver::class);
$image = $manager->read($this->getTestResourcePath('red.gif'));
$this->assertInstanceOf(ImageInterface::class, $image);
}
public function testReadImagickWithDecoderClassname(): void
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 testReadImagickWithDecoderInstance(): void
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 testReadImagickWithDecoderClassnameArray(): void
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 testReadImagickWithDecoderInstanceArray(): void
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 testReadImagickWithDecoderInstanceArrayMultiple(): void
public function testReadWithDecoderInstanceArrayMultiple(): void
{
$manager = new ImageManager(Driver::class);
$image = $manager->read($this->getTestResourcePath('red.gif'), [
@ -109,17 +109,49 @@ final class ImageManagerTestImagick extends BaseTestCase
$this->assertInstanceOf(ImageInterface::class, $image);
}
public function testReadImagickWithRotationAdjustment(): void
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 testReadImagickWithoutRotationAdjustment(): void
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));
}
}