From 839bc6a3c671ab30de3e5c258afa0775975de976 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Mon, 5 Aug 2024 16:38:16 +0200 Subject: [PATCH 1/8] Refactor code --- src/Drivers/Gd/Cloner.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Drivers/Gd/Cloner.php b/src/Drivers/Gd/Cloner.php index 3813a1be..8edc2023 100644 --- a/src/Drivers/Gd/Cloner.php +++ b/src/Drivers/Gd/Cloner.php @@ -50,10 +50,7 @@ class Cloner ColorInterface $background = new Color(255, 255, 255, 0) ): GdImage { // define size - $size = match (true) { - is_null($size) => new Rectangle(imagesx($gd), imagesy($gd)), - default => $size, - }; + $size = $size ? $size : new Rectangle(imagesx($gd), imagesy($gd)); // create new gd image with same size or new given size $clone = imagecreatetruecolor($size->width(), $size->height()); From 5e9b4aa681800809cec61dcc87074a489ce63aaa Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Mon, 5 Aug 2024 16:54:09 +0200 Subject: [PATCH 2/8] Rename method --- tests/Unit/Drivers/Gd/ClonerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Drivers/Gd/ClonerTest.php b/tests/Unit/Drivers/Gd/ClonerTest.php index fab41b25..7fd39699 100644 --- a/tests/Unit/Drivers/Gd/ClonerTest.php +++ b/tests/Unit/Drivers/Gd/ClonerTest.php @@ -48,7 +48,7 @@ final class ClonerTest extends BaseTestCase ); } - public function testCLoneBlended(): void + public function testCloneBlended(): void { $gd = imagecreatefromgif($this->getTestResourcePath('gradient.gif')); $clone = Cloner::cloneBlended($gd, new Color(255, 0, 255, 255)); From de7fb02efaa704253019fcd064ca3b7eedf5f5ad Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Fri, 9 Aug 2024 16:23:28 +0200 Subject: [PATCH 3/8] Update FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 5dd8eeeb..5db98ebc 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,3 @@ github: [Intervention] +ko_fi: interventionphp custom: https://paypal.me/interventionio From 5d5cf355e431acd645dcd9699cad5343315f7f70 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sat, 10 Aug 2024 08:42:19 +0200 Subject: [PATCH 4/8] Add ko-fi support badge --- .github/images/support.svg | 24 ++++++++++++++++++++++++ readme.md | 1 + 2 files changed, 25 insertions(+) create mode 100644 .github/images/support.svg diff --git a/.github/images/support.svg b/.github/images/support.svg new file mode 100644 index 00000000..af31794e --- /dev/null +++ b/.github/images/support.svg @@ -0,0 +1,24 @@ + + + + + + + + + Support me on Ko-fi + + + + + + Support me on Ko-fi + + + + + + + + + diff --git a/readme.md b/readme.md index bb082054..b922cefe 100644 --- a/readme.md +++ b/readme.md @@ -4,6 +4,7 @@ [![Latest Version](https://img.shields.io/packagist/v/intervention/image.svg)](https://packagist.org/packages/intervention/image) [![Build Status](https://github.com/Intervention/image/actions/workflows/run-tests.yml/badge.svg)](https://github.com/Intervention/image/actions) [![Monthly Downloads](https://img.shields.io/packagist/dm/intervention/image.svg)](https://packagist.org/packages/intervention/image/stats) +[![Support me on Ko-fi](https://raw.githubusercontent.com/Intervention/image/develop/.github/images/support.svg)](https://ko-fi.com/interventionphp) Intervention Image is a **PHP image processing library** that provides a simple and expressive way to create, edit, and compose images. It features a unified From 6196ff1eb946875f3ba4e490a60ba5b6d9aa02d4 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 11:38:33 +0200 Subject: [PATCH 5/8] Fix bug when loading png greyscale type turn image into rgb if colorspace if other than CMYK, RGB, HSL or HSV. this prevents working on greyscale colorspace images when loading from PNG color type greyscale format. --- .../Imagick/Decoders/NativeObjectDecoder.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php b/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php index 3f23902d..0799b92e 100644 --- a/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php +++ b/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php @@ -17,6 +17,13 @@ use Intervention\Image\Modifiers\RemoveAnimationModifier; class NativeObjectDecoder extends SpecializableDecoder implements SpecializedInterface { + protected const SUPPORTED_COLORSPACES = [ + Imagick::COLORSPACE_SRGB, + Imagick::COLORSPACE_CMYK, + Imagick::COLORSPACE_HSL, + Imagick::COLORSPACE_HSB, + ]; + public function decode(mixed $input): ImageInterface|ColorInterface { if (!is_object($input)) { @@ -34,6 +41,13 @@ class NativeObjectDecoder extends SpecializableDecoder implements SpecializedInt $input = $input->coalesceImages(); } + // turn image into rgb if colorspace if other than CMYK, RGB, HSL or HSV. + // this prevents working on greyscale colorspace images when loading + // from PNG color type greyscale format. + if (!in_array($input->getImageColorspace(), self::SUPPORTED_COLORSPACES)) { + $input->setImageColorspace(Imagick::COLORSPACE_SRGB); + } + // create image object $image = new Image( $this->driver(), From 4a614ddfb877928da852ce1090e79f8df68200ea Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 11:41:38 +0200 Subject: [PATCH 6/8] Implement new method ColorInterface::isClear() (#1387) --- src/Colors/Cmyk/Color.php | 10 ++++++++++ src/Colors/Hsl/Color.php | 10 ++++++++++ src/Colors/Hsv/Color.php | 10 ++++++++++ src/Colors/Rgb/Color.php | 10 ++++++++++ src/Interfaces/ColorInterface.php | 7 +++++++ tests/Unit/Colors/Cmyk/ColorTest.php | 6 ++++++ tests/Unit/Colors/Hsl/ColorTest.php | 6 ++++++ tests/Unit/Colors/Hsv/ColorTest.php | 6 ++++++ tests/Unit/Colors/Rgb/ColorTest.php | 15 +++++++++++++++ 9 files changed, 80 insertions(+) diff --git a/src/Colors/Cmyk/Color.php b/src/Colors/Cmyk/Color.php index 5aad25a4..d3229e6c 100644 --- a/src/Colors/Cmyk/Color.php +++ b/src/Colors/Cmyk/Color.php @@ -152,4 +152,14 @@ class Color extends AbstractColor { return false; } + + /** + * {@inheritdoc} + * + * @see ColorInterface::isClear() + */ + public function isClear(): bool + { + return false; + } } diff --git a/src/Colors/Hsl/Color.php b/src/Colors/Hsl/Color.php index e682f9a2..20ca0e5d 100644 --- a/src/Colors/Hsl/Color.php +++ b/src/Colors/Hsl/Color.php @@ -120,4 +120,14 @@ class Color extends AbstractColor { return false; } + + /** + * {@inheritdoc} + * + * @see ColorInterface::isClear() + */ + public function isClear(): bool + { + return false; + } } diff --git a/src/Colors/Hsv/Color.php b/src/Colors/Hsv/Color.php index 9c7f285c..8a4f18b2 100644 --- a/src/Colors/Hsv/Color.php +++ b/src/Colors/Hsv/Color.php @@ -120,4 +120,14 @@ class Color extends AbstractColor { return false; } + + /** + * {@inheritdoc} + * + * @see ColorInterface::isClear() + */ + public function isClear(): bool + { + return false; + } } diff --git a/src/Colors/Rgb/Color.php b/src/Colors/Rgb/Color.php index f97a9241..4926a73c 100644 --- a/src/Colors/Rgb/Color.php +++ b/src/Colors/Rgb/Color.php @@ -178,4 +178,14 @@ class Color extends AbstractColor { return $this->alpha()->value() < $this->alpha()->max(); } + + /** + * {@inheritdoc} + * + * @see ColorInterface::isClear() + */ + public function isClear(): bool + { + return $this->alpha()->value() == 0; + } } diff --git a/src/Interfaces/ColorInterface.php b/src/Interfaces/ColorInterface.php index 33c44bc7..b72f1fcc 100644 --- a/src/Interfaces/ColorInterface.php +++ b/src/Interfaces/ColorInterface.php @@ -97,4 +97,11 @@ interface ColorInterface * @return bool */ public function isTransparent(): bool; + + /** + * Determine whether the current color is completely transparent + * + * @return bool + */ + public function isClear(): bool; } diff --git a/tests/Unit/Colors/Cmyk/ColorTest.php b/tests/Unit/Colors/Cmyk/ColorTest.php index 3ae51d7d..7fae9ea4 100644 --- a/tests/Unit/Colors/Cmyk/ColorTest.php +++ b/tests/Unit/Colors/Cmyk/ColorTest.php @@ -111,4 +111,10 @@ final class ColorTest extends BaseTestCase $color = new Color(100, 50, 50, 0); $this->assertFalse($color->isTransparent()); } + + public function testIsClear(): void + { + $color = new Color(0, 0, 0, 0); + $this->assertFalse($color->isClear()); + } } diff --git a/tests/Unit/Colors/Hsl/ColorTest.php b/tests/Unit/Colors/Hsl/ColorTest.php index 9f503bf5..749d21b0 100644 --- a/tests/Unit/Colors/Hsl/ColorTest.php +++ b/tests/Unit/Colors/Hsl/ColorTest.php @@ -108,4 +108,10 @@ final class ColorTest extends BaseTestCase $color = new Color(0, 1, 0); $this->assertFalse($color->isTransparent()); } + + public function testIsClear(): void + { + $color = new Color(0, 1, 0); + $this->assertFalse($color->isClear()); + } } diff --git a/tests/Unit/Colors/Hsv/ColorTest.php b/tests/Unit/Colors/Hsv/ColorTest.php index 930c54ff..f4a270b2 100644 --- a/tests/Unit/Colors/Hsv/ColorTest.php +++ b/tests/Unit/Colors/Hsv/ColorTest.php @@ -108,4 +108,10 @@ final class ColorTest extends BaseTestCase $color = new Color(1, 0, 0); $this->assertFalse($color->isTransparent()); } + + public function testIsClear(): void + { + $color = new Color(0, 1, 0); + $this->assertFalse($color->isClear()); + } } diff --git a/tests/Unit/Colors/Rgb/ColorTest.php b/tests/Unit/Colors/Rgb/ColorTest.php index 6fb2051e..16bfd1ed 100644 --- a/tests/Unit/Colors/Rgb/ColorTest.php +++ b/tests/Unit/Colors/Rgb/ColorTest.php @@ -163,4 +163,19 @@ final class ColorTest extends BaseTestCase $color = new Color(255, 255, 255, 0); $this->assertTrue($color->isTransparent()); } + + public function testIsClear(): void + { + $color = new Color(255, 255, 255); + $this->assertFalse($color->isClear()); + + $color = new Color(255, 255, 255, 255); + $this->assertFalse($color->isClear()); + + $color = new Color(255, 255, 255, 85); + $this->assertFalse($color->isClear()); + + $color = new Color(255, 255, 255, 0); + $this->assertTrue($color->isClear()); + } } From 31779d02636a315ec3b53225308ddb95083539d4 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 11:43:54 +0200 Subject: [PATCH 7/8] Add ability to read instances of EncodedImaged::class (#1386) * Implement EncodedImageObjectDecoder::class * Add tests for EncodedImageObjectDecoder::class --- src/Decoders/EncodedImageObjectDecoder.php | 11 +++++++ .../Gd/Decoders/EncodedImageObjectDecoder.php | 27 ++++++++++++++++ .../Decoders/EncodedImageObjectDecoder.php | 27 ++++++++++++++++ src/InputHandler.php | 2 ++ .../EncodedImageObjectDecoderTest.php | 32 +++++++++++++++++++ .../EncodedImageObjectDecoderTest.php | 32 +++++++++++++++++++ 6 files changed, 131 insertions(+) create mode 100644 src/Decoders/EncodedImageObjectDecoder.php create mode 100644 src/Drivers/Gd/Decoders/EncodedImageObjectDecoder.php create mode 100644 src/Drivers/Imagick/Decoders/EncodedImageObjectDecoder.php create mode 100644 tests/Unit/Drivers/Gd/Decoders/EncodedImageObjectDecoderTest.php create mode 100644 tests/Unit/Drivers/Imagick/Decoders/EncodedImageObjectDecoderTest.php diff --git a/src/Decoders/EncodedImageObjectDecoder.php b/src/Decoders/EncodedImageObjectDecoder.php new file mode 100644 index 00000000..daddff2d --- /dev/null +++ b/src/Decoders/EncodedImageObjectDecoder.php @@ -0,0 +1,11 @@ +toString()); + } +} diff --git a/src/Drivers/Imagick/Decoders/EncodedImageObjectDecoder.php b/src/Drivers/Imagick/Decoders/EncodedImageObjectDecoder.php new file mode 100644 index 00000000..2348a6b7 --- /dev/null +++ b/src/Drivers/Imagick/Decoders/EncodedImageObjectDecoder.php @@ -0,0 +1,27 @@ +toString()); + } +} diff --git a/src/InputHandler.php b/src/InputHandler.php index 2772ec45..a0720d13 100644 --- a/src/InputHandler.php +++ b/src/InputHandler.php @@ -15,6 +15,7 @@ use Intervention\Image\Decoders\Base64ImageDecoder; use Intervention\Image\Decoders\BinaryImageDecoder; use Intervention\Image\Decoders\ColorObjectDecoder; use Intervention\Image\Decoders\DataUriImageDecoder; +use Intervention\Image\Decoders\EncodedImageObjectDecoder; use Intervention\Image\Decoders\FilePathImageDecoder; use Intervention\Image\Decoders\FilePointerImageDecoder; use Intervention\Image\Decoders\ImageObjectDecoder; @@ -53,6 +54,7 @@ class InputHandler implements InputHandlerInterface BinaryImageDecoder::class, DataUriImageDecoder::class, Base64ImageDecoder::class, + EncodedImageObjectDecoder::class, ]; /** diff --git a/tests/Unit/Drivers/Gd/Decoders/EncodedImageObjectDecoderTest.php b/tests/Unit/Drivers/Gd/Decoders/EncodedImageObjectDecoderTest.php new file mode 100644 index 00000000..f75762f1 --- /dev/null +++ b/tests/Unit/Drivers/Gd/Decoders/EncodedImageObjectDecoderTest.php @@ -0,0 +1,32 @@ +decoder = new EncodedImageObjectDecoder(); + $this->decoder->setDriver(new Driver()); + } + + public function testDecode(): void + { + $result = $this->decoder->decode(new EncodedImage($this->getTestResourceData())); + $this->assertInstanceOf(Image::class, $result); + } +} diff --git a/tests/Unit/Drivers/Imagick/Decoders/EncodedImageObjectDecoderTest.php b/tests/Unit/Drivers/Imagick/Decoders/EncodedImageObjectDecoderTest.php new file mode 100644 index 00000000..826498d3 --- /dev/null +++ b/tests/Unit/Drivers/Imagick/Decoders/EncodedImageObjectDecoderTest.php @@ -0,0 +1,32 @@ +decoder = new EncodedImageObjectDecoder(); + $this->decoder->setDriver(new Driver()); + } + + public function testDecode(): void + { + $result = $this->decoder->decode(new EncodedImage($this->getTestResourceData())); + $this->assertInstanceOf(Image::class, $result); + } +} From 9f5e0624d4b8d073f58f8bfef71ba8363d9fb688 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 12:02:30 +0200 Subject: [PATCH 8/8] Fix bug in cloner transparency (#1388) If an image was cloned with cloneEmpty() and a fully transparent color for exampe "rgba(255, 255, 255, 0)" the turned out as white background when encoding formats with only binary transparency like GIF. This patch sets the background color as fully transparent if it has an alpha channel value is below `0.5`. --- src/Drivers/Gd/Cloner.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Drivers/Gd/Cloner.php b/src/Drivers/Gd/Cloner.php index 8edc2023..8723006a 100644 --- a/src/Drivers/Gd/Cloner.php +++ b/src/Drivers/Gd/Cloner.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Intervention\Image\Drivers\Gd; use GdImage; +use Intervention\Image\Colors\Rgb\Channels\Alpha; use Intervention\Image\Colors\Rgb\Color; use Intervention\Image\Exceptions\ColorException; use Intervention\Image\Geometry\Rectangle; @@ -67,6 +68,12 @@ class Cloner imagealphablending($clone, true); imagesavealpha($clone, true); + // set background image as transparent if alpha channel value if color is below .5 + // comes into effect when the end format only supports binary transparency (like GIF) + if ($background->channel(Alpha::class)->value() < 128) { + imagecolortransparent($clone, $processor->colorToNative($background)); + } + return $clone; }