From 2d565be6cbbf95accdccc1f1465bf3103601c21d Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Thu, 26 Oct 2023 15:37:24 +0200 Subject: [PATCH] Refine color profiles - Add tests for profile methods - Add ProfileInterface - Add profile methods to ImageInterface --- src/Colors/Profile.php | 3 ++- src/Drivers/Gd/Image.php | 36 +++++++++++++++++++++++++++++ src/Drivers/Imagick/Image.php | 28 ++++++++++++++++------ src/Interfaces/ImageInterface.php | 22 ++++++++++++++++++ src/Interfaces/ProfileInterface.php | 8 +++++++ tests/Drivers/Imagick/ImageTest.php | 24 +++++++++++++++++++ 6 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 src/Interfaces/ProfileInterface.php diff --git a/src/Colors/Profile.php b/src/Colors/Profile.php index f0a847fd..b2b909a4 100644 --- a/src/Colors/Profile.php +++ b/src/Colors/Profile.php @@ -3,8 +3,9 @@ namespace Intervention\Image\Colors; use Intervention\Image\GenericData; +use Intervention\Image\Interfaces\ProfileInterface; -class Profile extends GenericData +class Profile extends GenericData implements ProfileInterface { // } diff --git a/src/Drivers/Gd/Image.php b/src/Drivers/Gd/Image.php index 2e34f3d0..dca13335 100644 --- a/src/Drivers/Gd/Image.php +++ b/src/Drivers/Gd/Image.php @@ -11,6 +11,7 @@ use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\ColorspaceInterface; use Intervention\Image\Interfaces\FrameInterface; use Intervention\Image\Interfaces\ImageInterface; +use Intervention\Image\Interfaces\ProfileInterface; use IteratorAggregate; use Traversable; @@ -83,6 +84,11 @@ class Image extends AbstractImage implements ImageInterface, IteratorAggregate return null; } + /** + * {@inheritdoc} + * + * @see ImageInterface::getColorspace() + */ public function getColorspace(): ColorspaceInterface { return new RgbColorspace(); @@ -105,4 +111,34 @@ class Image extends AbstractImage implements ImageInterface, IteratorAggregate return $this; } + + /** + * {@inheritdoc} + * + * @see ImageInterface::setProfile() + */ + public function setProfile(string|ProfileInterface $input): ImageInterface + { + throw new NotSupportedException('Color profiles are not supported by GD driver.'); + } + + /** + * {@inheritdoc} + * + * @see ImageInterface::profile() + */ + public function profile(): ProfileInterface + { + throw new NotSupportedException('Color profiles are not supported by GD driver.'); + } + + /** + * {@inheritdoc} + * + * @see ImageInterface::withoutProfile() + */ + public function withoutProfile(): ImageInterface + { + throw new NotSupportedException('Color profiles are not supported by GD driver.'); + } } diff --git a/src/Drivers/Imagick/Image.php b/src/Drivers/Imagick/Image.php index 11c2748e..350fc39b 100644 --- a/src/Drivers/Imagick/Image.php +++ b/src/Drivers/Imagick/Image.php @@ -17,6 +17,7 @@ use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\ColorspaceInterface; use Intervention\Image\Interfaces\FrameInterface; use Intervention\Image\Interfaces\ImageInterface; +use Intervention\Image\Interfaces\ProfileInterface; use Iterator; class Image extends AbstractImage implements ImageInterface, Iterator @@ -162,16 +163,24 @@ class Image extends AbstractImage implements ImageInterface, Iterator return $this->modify(new ColorspaceModifier($colorspace)); } - public function setProfile(string $filepath): ImageInterface + /** + * {@inheritdoc} + * + * @see ImageInterface::setProfile() + */ + public function setProfile(string|ProfileInterface $input): ImageInterface { - return $this->modify( - new ProfileModifier( - new Profile(file_get_contents($filepath)) - ) - ); + $profile = is_object($input) ? $input : new Profile(file_get_contents($input)); + + return $this->modify(new ProfileModifier($profile)); } - public function getProfile(): Profile + /** + * {@inheritdoc} + * + * @see ImageInterface::profile() + */ + public function profile(): ProfileInterface { $profiles = $this->imagick->getImageProfiles('icc'); @@ -182,6 +191,11 @@ class Image extends AbstractImage implements ImageInterface, Iterator return new Profile($profiles['icc']); } + /** + * {@inheritdoc} + * + * @see ImageInterface::withoutProfile() + */ public function withoutProfile(): ImageInterface { return $this->modify(new ProfileRemovalModifier()); diff --git a/src/Interfaces/ImageInterface.php b/src/Interfaces/ImageInterface.php index 12646f9e..83c428b4 100644 --- a/src/Interfaces/ImageInterface.php +++ b/src/Interfaces/ImageInterface.php @@ -155,6 +155,28 @@ interface ImageInterface extends Traversable, Countable */ public function setColorspace(string|ColorspaceInterface $target): ImageInterface; + /** + * Retrieve ICC color profile of image + * + * @return ProfileInterface + */ + public function profile(): ProfileInterface; + + /** + * Set ICC color profile on the current image + * + * @param string|ProfileInterface $input Path to color profile or profile object + * @return ImageInterface + */ + public function setProfile(string|ProfileInterface $input): ImageInterface; + + /** + * Remove ICC color profile from the current image + * + * @return ImageInterface + */ + public function withoutProfile(): ImageInterface; + /** * Draw text on image * diff --git a/src/Interfaces/ProfileInterface.php b/src/Interfaces/ProfileInterface.php new file mode 100644 index 00000000..4a3d8e59 --- /dev/null +++ b/src/Interfaces/ProfileInterface.php @@ -0,0 +1,8 @@ +assertInstanceOf(Image::class, $result); $this->assertInstanceOf(CmykColorspace::class, $result->getColorspace()); } + + public function testSetGetProfile(): void + { + $imagick = new Imagick(); + $imagick->readImageBlob($this->getTestImageData('test.jpg')); + $image = new Image($imagick); + $result = $image->profile(); + $this->assertInstanceOf(Profile::class, $result); + $result = $image->setProfile($result); + $this->assertInstanceOf(Image::class, $result); + } + + public function testWithoutProfile(): void + { + $imagick = new Imagick(); + $imagick->readImageBlob($this->getTestImageData('test.jpg')); + $image = new Image($imagick); + $result = $image->withoutProfile(); + $this->assertInstanceOf(Image::class, $result); + $this->expectException(ColorException::class); + $image->profile(); + } }