From ce4d2bc75c012d03962a06ab02427ebba8b59757 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 28 Jul 2024 08:42:12 +0200 Subject: [PATCH 01/23] Set imagick image formats to uppercase --- src/Drivers/Imagick/Encoders/BmpEncoder.php | 2 +- src/Drivers/Imagick/Encoders/GifEncoder.php | 2 +- src/Drivers/Imagick/Encoders/Jpeg2000Encoder.php | 2 +- src/Drivers/Imagick/Encoders/JpegEncoder.php | 2 +- src/Drivers/Imagick/Encoders/PngEncoder.php | 2 +- src/Drivers/Imagick/Encoders/WebpEncoder.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Drivers/Imagick/Encoders/BmpEncoder.php b/src/Drivers/Imagick/Encoders/BmpEncoder.php index 293767de..c5876228 100644 --- a/src/Drivers/Imagick/Encoders/BmpEncoder.php +++ b/src/Drivers/Imagick/Encoders/BmpEncoder.php @@ -14,7 +14,7 @@ class BmpEncoder extends GenericBmpEncoder implements SpecializedInterface { public function encode(ImageInterface $image): EncodedImage { - $format = 'bmp'; + $format = 'BMP'; $compression = Imagick::COMPRESSION_NO; $imagick = $image->core()->native(); diff --git a/src/Drivers/Imagick/Encoders/GifEncoder.php b/src/Drivers/Imagick/Encoders/GifEncoder.php index 41783a39..3670fdc6 100644 --- a/src/Drivers/Imagick/Encoders/GifEncoder.php +++ b/src/Drivers/Imagick/Encoders/GifEncoder.php @@ -14,7 +14,7 @@ class GifEncoder extends GenericGifEncoder implements SpecializedInterface { public function encode(ImageInterface $image): EncodedImage { - $format = 'gif'; + $format = 'GIF'; $compression = Imagick::COMPRESSION_LZW; $imagick = $image->core()->native(); diff --git a/src/Drivers/Imagick/Encoders/Jpeg2000Encoder.php b/src/Drivers/Imagick/Encoders/Jpeg2000Encoder.php index db0cc13a..5c4bd59e 100644 --- a/src/Drivers/Imagick/Encoders/Jpeg2000Encoder.php +++ b/src/Drivers/Imagick/Encoders/Jpeg2000Encoder.php @@ -15,7 +15,7 @@ class Jpeg2000Encoder extends GenericJpeg2000Encoder implements SpecializedInter { public function encode(ImageInterface $image): EncodedImageInterface { - $format = 'jp2'; + $format = 'JP2'; $compression = Imagick::COMPRESSION_JPEG; $imagick = $image->core()->native(); diff --git a/src/Drivers/Imagick/Encoders/JpegEncoder.php b/src/Drivers/Imagick/Encoders/JpegEncoder.php index 9484f3ca..7772d88e 100644 --- a/src/Drivers/Imagick/Encoders/JpegEncoder.php +++ b/src/Drivers/Imagick/Encoders/JpegEncoder.php @@ -14,7 +14,7 @@ class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface { public function encode(ImageInterface $image): EncodedImage { - $format = 'jpeg'; + $format = 'JPEG'; $compression = Imagick::COMPRESSION_JPEG; $blendingColor = $this->driver()->handleInput( $this->driver()->config()->blendingColor diff --git a/src/Drivers/Imagick/Encoders/PngEncoder.php b/src/Drivers/Imagick/Encoders/PngEncoder.php index b6614ba1..79ef2412 100644 --- a/src/Drivers/Imagick/Encoders/PngEncoder.php +++ b/src/Drivers/Imagick/Encoders/PngEncoder.php @@ -14,7 +14,7 @@ class PngEncoder extends GenericPngEncoder implements SpecializedInterface { public function encode(ImageInterface $image): EncodedImage { - $format = 'png'; + $format = 'PNG'; $compression = Imagick::COMPRESSION_ZIP; $imagick = $image->core()->native(); diff --git a/src/Drivers/Imagick/Encoders/WebpEncoder.php b/src/Drivers/Imagick/Encoders/WebpEncoder.php index 93a26fd9..8b19f2ac 100644 --- a/src/Drivers/Imagick/Encoders/WebpEncoder.php +++ b/src/Drivers/Imagick/Encoders/WebpEncoder.php @@ -15,7 +15,7 @@ class WebpEncoder extends GenericWebpEncoder implements SpecializedInterface { public function encode(ImageInterface $image): EncodedImage { - $format = 'webp'; + $format = 'WEBP'; $compression = Imagick::COMPRESSION_ZIP; $imagick = $image->core()->native(); From 66040006f320159168dff5eb70dba02ef218aa8a Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sat, 3 Aug 2024 10:56:34 +0200 Subject: [PATCH 02/23] Implement 'indexed' option in PNG encoders --- src/Drivers/Gd/Encoders/PngEncoder.php | 60 ++++++++++++++++-- src/Drivers/Imagick/Encoders/PngEncoder.php | 69 ++++++++++++++++++--- src/Encoders/PngEncoder.php | 2 +- 3 files changed, 116 insertions(+), 15 deletions(-) diff --git a/src/Drivers/Gd/Encoders/PngEncoder.php b/src/Drivers/Gd/Encoders/PngEncoder.php index 6b20ea91..bd6a90c0 100644 --- a/src/Drivers/Gd/Encoders/PngEncoder.php +++ b/src/Drivers/Gd/Encoders/PngEncoder.php @@ -4,22 +4,72 @@ namespace Intervention\Image\Drivers\Gd\Encoders; +use GdImage; +use Intervention\Image\Drivers\Gd\Cloner; use Intervention\Image\EncodedImage; use Intervention\Image\Encoders\PngEncoder as GenericPngEncoder; +use Intervention\Image\Exceptions\AnimationException; +use Intervention\Image\Exceptions\ColorException; +use Intervention\Image\Exceptions\RuntimeException; use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\SpecializedInterface; class PngEncoder extends GenericPngEncoder implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see EncoderInterface::encode() + */ public function encode(ImageInterface $image): EncodedImage { - $gd = $image->core()->native(); - $data = $this->buffered(function () use ($gd) { - imageinterlace($gd, $this->interlaced); - imagepng($gd, null, -1); - imageinterlace($gd, false); + $output = $this->prepareOutput($image); + + // encode + $data = $this->buffered(function () use ($output) { + imageinterlace($output, $this->interlaced); + imagepng($output, null, -1); }); return new EncodedImage($data, 'image/png'); } + + /** + * Prepare given image instance for PNG format output according to encoder settings + * + * @param ImageInterface $image + * @param bool $indexed + * @throws RuntimeException + * @throws ColorException + * @throws AnimationException + * @return GdImage + */ + private function prepareOutput(ImageInterface $image): GdImage + { + if ($this->indexed === false) { + return Cloner::clone($image->core()->native()); + } + + // get blending color + $blendingColor = $this->driver()->colorProcessor($image->colorspace())->colorToNative( + $this->driver()->handleInput($this->driver()->config()->blendingColor) + ); + + // clone output instance + $output = Cloner::cloneEmpty($image->core()->native()); + + // fill with blending color + imagefill($output, 0, 0, $blendingColor); + + // set transparency + imagecolortransparent($output, $blendingColor); + + // copy original into output + imagecopy($output, $image->core()->native(), 0, 0, 0, 0, imagesx($output), imagesy($output)); + + // reduce to indexed color palette + imagetruecolortopalette($output, true, 255); + + return $output; + } } diff --git a/src/Drivers/Imagick/Encoders/PngEncoder.php b/src/Drivers/Imagick/Encoders/PngEncoder.php index 79ef2412..06a7a03d 100644 --- a/src/Drivers/Imagick/Encoders/PngEncoder.php +++ b/src/Drivers/Imagick/Encoders/PngEncoder.php @@ -5,28 +5,79 @@ namespace Intervention\Image\Drivers\Imagick\Encoders; use Imagick; +use ImagickException; use Intervention\Image\EncodedImage; use Intervention\Image\Encoders\PngEncoder as GenericPngEncoder; +use Intervention\Image\Exceptions\AnimationException; +use Intervention\Image\Exceptions\RuntimeException; +use Intervention\Image\Exceptions\ColorException; use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\SpecializedInterface; class PngEncoder extends GenericPngEncoder implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see EncoderInterface::encode() + */ public function encode(ImageInterface $image): EncodedImage { - $format = 'PNG'; - $compression = Imagick::COMPRESSION_ZIP; + $output = $this->prepareOutput($image); - $imagick = $image->core()->native(); - $imagick->setFormat($format); - $imagick->setImageFormat($format); - $imagick->setCompression($compression); - $imagick->setImageCompression($compression); + $output->setCompression(Imagick::COMPRESSION_ZIP); + $output->setImageCompression(Imagick::COMPRESSION_ZIP); if ($this->interlaced) { - $imagick->setInterlaceScheme(Imagick::INTERLACE_LINE); + $output->setInterlaceScheme(Imagick::INTERLACE_LINE); } - return new EncodedImage($imagick->getImagesBlob(), 'image/png'); + return new EncodedImage($output->getImagesBlob(), 'image/png'); + } + + /** + * Prepare given image instance for PNG format output according to encoder settings + * + * @param ImageInterface $image + * @throws AnimationException + * @throws RuntimeException + * @throws ColorException + * @throws ImagickException + * @return Imagick + */ + private function prepareOutput(ImageInterface $image): Imagick + { + if ($this->indexed === false) { + $output = clone $image->core()->native(); + + // ensure to encode PNG image type 6 true color alpha + $output->setFormat('PNG32'); + $output->setImageFormat('PNG32'); + + return $output; + } + + // get blending color + $blendingColor = $this->driver()->colorProcessor($image->colorspace())->colorToNative( + $this->driver()->handleInput($this->driver()->config()->blendingColor) + ); + + // create new image with blending color as background + $output = new Imagick(); + $output->newImage($image->width(), $image->height(), $blendingColor, 'PNG'); + + // set transparency of original image + $output->compositeImage($image->core()->native(), Imagick::COMPOSITE_DSTIN, 0, 0); + $output->transparentPaintImage('#000000', 0, 0, false); + + // copy original and create indexed color palette version + $output->compositeImage($image->core()->native(), Imagick::COMPOSITE_DEFAULT, 0, 0); + $output->quantizeImage(255, $output->getImageColorSpace(), 0, false, false); + + // ensure to encode PNG image type 3 (indexed) + $output->setFormat('PNG8'); + $output->setImageFormat('PNG8'); + + return $output; } } diff --git a/src/Encoders/PngEncoder.php b/src/Encoders/PngEncoder.php index b6bb6cb5..7b2df853 100644 --- a/src/Encoders/PngEncoder.php +++ b/src/Encoders/PngEncoder.php @@ -8,7 +8,7 @@ class PngEncoder extends SpecializableEncoder { - public function __construct(public bool $interlaced = false) + public function __construct(public bool $interlaced = false, public bool $indexed = false) { } } From 460b20568781c1fc83aa23f1fea532d1730b134a Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sat, 3 Aug 2024 11:03:32 +0200 Subject: [PATCH 03/23] Rename class --- .../{CanDetectInterlacedPng.php => CanInspectPngFormat.php} | 2 +- tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php | 4 ++-- tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename tests/Traits/{CanDetectInterlacedPng.php => CanInspectPngFormat.php} (94%) diff --git a/tests/Traits/CanDetectInterlacedPng.php b/tests/Traits/CanInspectPngFormat.php similarity index 94% rename from tests/Traits/CanDetectInterlacedPng.php rename to tests/Traits/CanInspectPngFormat.php index 19fffe46..510466f7 100644 --- a/tests/Traits/CanDetectInterlacedPng.php +++ b/tests/Traits/CanInspectPngFormat.php @@ -6,7 +6,7 @@ use Intervention\Image\Traits\CanBuildFilePointer; -trait CanDetectInterlacedPng +trait CanInspectPngFormat { use CanBuildFilePointer; diff --git a/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php b/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php index 9c96591a..69cc7d12 100644 --- a/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php +++ b/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php @@ -8,14 +8,14 @@ use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Encoders\PngEncoder; use Intervention\Image\Tests\GdTestCase; -use Intervention\Image\Tests\Traits\CanDetectInterlacedPng; +use Intervention\Image\Tests\Traits\CanInspectPngFormat; #[RequiresPhpExtension('gd')] #[CoversClass(\Intervention\Image\Encoders\PngEncoder::class)] #[CoversClass(\Intervention\Image\Drivers\Gd\Encoders\PngEncoder::class)] final class PngEncoderTest extends GdTestCase { - use CanDetectInterlacedPng; + use CanInspectPngFormat; public function testEncode(): void { diff --git a/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php b/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php index 503320b7..268ac830 100644 --- a/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php +++ b/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php @@ -8,14 +8,14 @@ use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Encoders\PngEncoder; use Intervention\Image\Tests\ImagickTestCase; -use Intervention\Image\Tests\Traits\CanDetectInterlacedPng; +use Intervention\Image\Tests\Traits\CanInspectPngFormat; #[RequiresPhpExtension('imagick')] #[CoversClass(\Intervention\Image\Encoders\PngEncoder::class)] #[CoversClass(\Intervention\Image\Drivers\Imagick\Encoders\PngEncoder::class)] final class PngEncoderTest extends ImagickTestCase { - use CanDetectInterlacedPng; + use CanInspectPngFormat; public function testEncode(): void { From 2ee997d98fd08a5a4a54adc5bf0726bc2b563e12 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sat, 3 Aug 2024 11:04:30 +0200 Subject: [PATCH 04/23] Add method to detect PNG color types --- tests/Traits/CanInspectPngFormat.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/Traits/CanInspectPngFormat.php b/tests/Traits/CanInspectPngFormat.php index 510466f7..c09a4f7f 100644 --- a/tests/Traits/CanInspectPngFormat.php +++ b/tests/Traits/CanInspectPngFormat.php @@ -24,4 +24,29 @@ private function isInterlacedPng(string $imagedata): bool return ord($contents[28]) != 0; } + + /** + * Try to detect PNG color type from given binary data + * + * @param string $data + * @return string + */ + private function pngColorType(string $data): string + { + if (substr($data, 1, 3) !== 'PNG') { + return 'unkown'; + } + + $pos = strpos($data, 'IHDR'); + $type = substr($data, $pos + 13, 1); + + return match (unpack('C', $type)[1]) { + 0 => 'grayscale', + 2 => 'truecolor', + 3 => 'indexed', + 4 => 'grayscale-alpha', + 6 => 'truecolor-alpha', + default => 'unknown', + }; + } } From 63990a8fb3352f69ade4fdffbf680043cd02183a Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sat, 3 Aug 2024 11:15:29 +0200 Subject: [PATCH 05/23] Add tests for PNG indexed options --- src/Drivers/Gd/Encoders/PngEncoder.php | 3 +- src/Drivers/Imagick/Encoders/PngEncoder.php | 2 +- tests/BaseTestCase.php | 2 +- tests/GdTestCase.php | 8 +-- tests/ImagickTestCase.php | 8 +-- .../Drivers/Gd/Encoders/PngEncoderTest.php | 57 +++++++++++++++++++ .../Imagick/Encoders/PngEncoderTest.php | 57 +++++++++++++++++++ 7 files changed, 125 insertions(+), 12 deletions(-) diff --git a/src/Drivers/Gd/Encoders/PngEncoder.php b/src/Drivers/Gd/Encoders/PngEncoder.php index bd6a90c0..8368b7a6 100644 --- a/src/Drivers/Gd/Encoders/PngEncoder.php +++ b/src/Drivers/Gd/Encoders/PngEncoder.php @@ -38,7 +38,6 @@ public function encode(ImageInterface $image): EncodedImage * Prepare given image instance for PNG format output according to encoder settings * * @param ImageInterface $image - * @param bool $indexed * @throws RuntimeException * @throws ColorException * @throws AnimationException @@ -51,7 +50,7 @@ private function prepareOutput(ImageInterface $image): GdImage } // get blending color - $blendingColor = $this->driver()->colorProcessor($image->colorspace())->colorToNative( + $blendingColor = $this->driver()->colorProcessor($image->colorspace())->colorToNative( $this->driver()->handleInput($this->driver()->config()->blendingColor) ); diff --git a/src/Drivers/Imagick/Encoders/PngEncoder.php b/src/Drivers/Imagick/Encoders/PngEncoder.php index 06a7a03d..c3889b18 100644 --- a/src/Drivers/Imagick/Encoders/PngEncoder.php +++ b/src/Drivers/Imagick/Encoders/PngEncoder.php @@ -58,7 +58,7 @@ private function prepareOutput(ImageInterface $image): Imagick } // get blending color - $blendingColor = $this->driver()->colorProcessor($image->colorspace())->colorToNative( + $blendingColor = $this->driver()->colorProcessor($image->colorspace())->colorToNative( $this->driver()->handleInput($this->driver()->config()->blendingColor) ); diff --git a/tests/BaseTestCase.php b/tests/BaseTestCase.php index 41caa2aa..9aa89c0c 100644 --- a/tests/BaseTestCase.php +++ b/tests/BaseTestCase.php @@ -25,7 +25,7 @@ public static function getTestResourceData($filename = 'test.jpg'): string return file_get_contents(self::getTestResourcePath($filename)); } - public function getTestResourcePointer($filename = 'test.jpg') + public static function getTestResourcePointer($filename = 'test.jpg') { $pointer = fopen('php://temp', 'rw'); fputs($pointer, self::getTestResourceData($filename)); diff --git a/tests/GdTestCase.php b/tests/GdTestCase.php index 2cfa9527..ebe98a01 100644 --- a/tests/GdTestCase.php +++ b/tests/GdTestCase.php @@ -12,14 +12,14 @@ abstract class GdTestCase extends BaseTestCase { - public function readTestImage($filename = 'test.jpg'): Image + public static function readTestImage($filename = 'test.jpg'): Image { return (new Driver())->specialize(new FilePathImageDecoder())->decode( - $this->getTestResourcePath($filename) + static::getTestResourcePath($filename) ); } - public function createTestImage(int $width, int $height): Image + public static function createTestImage(int $width, int $height): Image { $gd = imagecreatetruecolor($width, $height); imagefill($gd, 0, 0, imagecolorallocate($gd, 255, 0, 0)); @@ -32,7 +32,7 @@ public function createTestImage(int $width, int $height): Image ); } - public function createTestAnimation(): Image + public static function createTestAnimation(): Image { $gd1 = imagecreatetruecolor(3, 2); imagefill($gd1, 0, 0, imagecolorallocate($gd1, 255, 0, 0)); diff --git a/tests/ImagickTestCase.php b/tests/ImagickTestCase.php index cbd24dcc..bef7b674 100644 --- a/tests/ImagickTestCase.php +++ b/tests/ImagickTestCase.php @@ -13,14 +13,14 @@ abstract class ImagickTestCase extends BaseTestCase { - public function readTestImage($filename = 'test.jpg'): Image + public static function readTestImage($filename = 'test.jpg'): Image { return (new Driver())->specialize(new FilePathImageDecoder())->decode( - $this->getTestResourcePath($filename) + static::getTestResourcePath($filename) ); } - public function createTestImage(int $width, int $height): Image + public static function createTestImage(int $width, int $height): Image { $background = new ImagickPixel('rgb(255, 0, 0)'); $imagick = new Imagick(); @@ -36,7 +36,7 @@ public function createTestImage(int $width, int $height): Image ); } - public function createTestAnimation(): Image + public static function createTestAnimation(): Image { $imagick = new Imagick(); $imagick->setFormat('gif'); diff --git a/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php b/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php index 69cc7d12..d9bf1da4 100644 --- a/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php +++ b/tests/Unit/Drivers/Gd/Encoders/PngEncoderTest.php @@ -7,8 +7,10 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Encoders\PngEncoder; +use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Tests\GdTestCase; use Intervention\Image\Tests\Traits\CanInspectPngFormat; +use PHPUnit\Framework\Attributes\DataProvider; #[RequiresPhpExtension('gd')] #[CoversClass(\Intervention\Image\Encoders\PngEncoder::class)] @@ -34,4 +36,59 @@ public function testEncodeInterlaced(): void $this->assertMediaType('image/png', (string) $result); $this->assertTrue($this->isInterlacedPng((string) $result)); } + + #[DataProvider('indexedDataProvider')] + public function testEncoderIndexed(ImageInterface $image, PngEncoder $encoder, string $result): void + { + $this->assertEquals( + $result, + $this->pngColorType((string) $encoder->encode($image)), + ); + } + + public static function indexedDataProvider(): array + { + return [ + [ + static::createTestImage(3, 2), // new + new PngEncoder(indexed: false), + 'truecolor-alpha', + ], + [ + static::createTestImage(3, 2), // new + new PngEncoder(indexed: true), + 'indexed', + ], + [ + static::readTestImage('circle.png'), // truecolor-alpha + new PngEncoder(indexed: false), + 'truecolor-alpha', + ], + [ + static::readTestImage('circle.png'), // indexedcolor-alpha + new PngEncoder(indexed: true), + 'indexed', + ], + [ + static::readTestImage('tile.png'), // indexed + new PngEncoder(indexed: false), + 'truecolor-alpha', + ], + [ + static::readTestImage('tile.png'), // indexed + new PngEncoder(indexed: true), + 'indexed', + ], + [ + static::readTestImage('test.jpg'), // jpeg + new PngEncoder(indexed: false), + 'truecolor-alpha', + ], + [ + static::readTestImage('test.jpg'), // jpeg + new PngEncoder(indexed: true), + 'indexed', + ], + ]; + } } diff --git a/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php b/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php index 268ac830..b905bd28 100644 --- a/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php +++ b/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php @@ -7,8 +7,10 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Encoders\PngEncoder; +use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Tests\ImagickTestCase; use Intervention\Image\Tests\Traits\CanInspectPngFormat; +use PHPUnit\Framework\Attributes\DataProvider; #[RequiresPhpExtension('imagick')] #[CoversClass(\Intervention\Image\Encoders\PngEncoder::class)] @@ -34,4 +36,59 @@ public function testEncodeInterlaced(): void $this->assertMediaType('image/png', (string) $result); $this->assertTrue($this->isInterlacedPng((string) $result)); } + + #[DataProvider('indexedDataProvider')] + public function testEncoderIndexed(ImageInterface $image, PngEncoder $encoder, string $result): void + { + $this->assertEquals( + $result, + $this->pngColorType((string) $encoder->encode($image)), + ); + } + + public static function indexedDataProvider(): array + { + return [ + [ + static::createTestImage(3, 2), // new + new PngEncoder(indexed: false), + 'truecolor-alpha', + ], + [ + static::createTestImage(3, 2), // new + new PngEncoder(indexed: true), + 'indexed', + ], + [ + static::readTestImage('circle.png'), // truecolor-alpha + new PngEncoder(indexed: false), + 'truecolor-alpha', + ], + [ + static::readTestImage('circle.png'), // indexedcolor-alpha + new PngEncoder(indexed: true), + 'indexed', + ], + [ + static::readTestImage('tile.png'), // indexed + new PngEncoder(indexed: false), + 'truecolor-alpha', + ], + [ + static::readTestImage('tile.png'), // indexed + new PngEncoder(indexed: true), + 'indexed', + ], + [ + static::readTestImage('test.jpg'), // jpeg + new PngEncoder(indexed: false), + 'truecolor-alpha', + ], + [ + static::readTestImage('test.jpg'), // jpeg + new PngEncoder(indexed: true), + 'indexed', + ], + ]; + } } From 2adc3b45dec8f8f2469d1559738867e186a29620 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sat, 3 Aug 2024 17:04:44 +0200 Subject: [PATCH 06/23] Fix blending problem in GD's PngEncoder --- src/Drivers/Gd/Encoders/PngEncoder.php | 30 +++++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/Drivers/Gd/Encoders/PngEncoder.php b/src/Drivers/Gd/Encoders/PngEncoder.php index 8368b7a6..3e4fdec8 100644 --- a/src/Drivers/Gd/Encoders/PngEncoder.php +++ b/src/Drivers/Gd/Encoders/PngEncoder.php @@ -5,6 +5,7 @@ namespace Intervention\Image\Drivers\Gd\Encoders; use GdImage; +use Intervention\Image\Colors\Rgb\Color; use Intervention\Image\Drivers\Gd\Cloner; use Intervention\Image\EncodedImage; use Intervention\Image\Encoders\PngEncoder as GenericPngEncoder; @@ -49,19 +50,32 @@ private function prepareOutput(ImageInterface $image): GdImage return Cloner::clone($image->core()->native()); } - // get blending color - $blendingColor = $this->driver()->colorProcessor($image->colorspace())->colorToNative( - $this->driver()->handleInput($this->driver()->config()->blendingColor) - ); - // clone output instance $output = Cloner::cloneEmpty($image->core()->native()); + /** + * Decode configured blending color + * + * @var Color + */ + $blendingColor = $this->driver()->handleInput($this->driver()->config()->blendingColor); + + // allocate blending color with slighty different alpha value + // to avoid "overwriting" pixels with the same color in the + // original image with transprency + $blendingIndex = imagecolorallocatealpha( + $output, + $blendingColor->red()->value(), + $blendingColor->green()->value(), + $blendingColor->blue()->value(), + 1, + ); + // fill with blending color - imagefill($output, 0, 0, $blendingColor); + imagefill($output, 0, 0, $blendingIndex); - // set transparency - imagecolortransparent($output, $blendingColor); + // define blending index as transparent + imagecolortransparent($output, $blendingIndex); // copy original into output imagecopy($output, $image->core()->native(), 0, 0, 0, 0, imagesx($output), imagesy($output)); From 68479181fc880d624013b0ad657233d66606cd07 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 4 Aug 2024 08:41:09 +0200 Subject: [PATCH 07/23] Reactivate blending color methods on ImageInterface --- src/Drivers/Gd/Encoders/PngEncoder.php | 8 ++------ src/Interfaces/ImageInterface.php | 2 -- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Drivers/Gd/Encoders/PngEncoder.php b/src/Drivers/Gd/Encoders/PngEncoder.php index 3e4fdec8..b4600a83 100644 --- a/src/Drivers/Gd/Encoders/PngEncoder.php +++ b/src/Drivers/Gd/Encoders/PngEncoder.php @@ -53,12 +53,8 @@ private function prepareOutput(ImageInterface $image): GdImage // clone output instance $output = Cloner::cloneEmpty($image->core()->native()); - /** - * Decode configured blending color - * - * @var Color - */ - $blendingColor = $this->driver()->handleInput($this->driver()->config()->blendingColor); + // Decode configured blending color + $blendingColor = $image->blendingColor(); // allocate blending color with slighty different alpha value // to avoid "overwriting" pixels with the same color in the diff --git a/src/Interfaces/ImageInterface.php b/src/Interfaces/ImageInterface.php index 726c5207..efd9e221 100644 --- a/src/Interfaces/ImageInterface.php +++ b/src/Interfaces/ImageInterface.php @@ -254,7 +254,6 @@ public function pickColors(int $x, int $y): CollectionInterface; * Return color that is mixed with transparent areas when converting to a format which * does not support transparency. * - * @deprecated Use configuration options of image manager instead * @throws RuntimeException * @return ColorInterface */ @@ -264,7 +263,6 @@ public function blendingColor(): ColorInterface; * Set blending color will have no effect unless image is converted into a format * which does not support transparency. * - * @deprecated Use configuration options of image manager instead * @param mixed $color * @throws RuntimeException * @return ImageInterface From 50feb11dced7d619e163757c95ddbb9e3b3a25dc Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 4 Aug 2024 08:44:12 +0200 Subject: [PATCH 08/23] Refactor code --- src/Drivers/Gd/Encoders/PngEncoder.php | 10 ++++++---- src/Drivers/Imagick/Encoders/PngEncoder.php | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Drivers/Gd/Encoders/PngEncoder.php b/src/Drivers/Gd/Encoders/PngEncoder.php index b4600a83..0c3f810b 100644 --- a/src/Drivers/Gd/Encoders/PngEncoder.php +++ b/src/Drivers/Gd/Encoders/PngEncoder.php @@ -5,7 +5,9 @@ namespace Intervention\Image\Drivers\Gd\Encoders; use GdImage; -use Intervention\Image\Colors\Rgb\Color; +use Intervention\Image\Colors\Rgb\Channels\Blue; +use Intervention\Image\Colors\Rgb\Channels\Green; +use Intervention\Image\Colors\Rgb\Channels\Red; use Intervention\Image\Drivers\Gd\Cloner; use Intervention\Image\EncodedImage; use Intervention\Image\Encoders\PngEncoder as GenericPngEncoder; @@ -61,9 +63,9 @@ private function prepareOutput(ImageInterface $image): GdImage // original image with transprency $blendingIndex = imagecolorallocatealpha( $output, - $blendingColor->red()->value(), - $blendingColor->green()->value(), - $blendingColor->blue()->value(), + $blendingColor->channel(Red::class)->value(), + $blendingColor->channel(Green::class)->value(), + $blendingColor->channel(Blue::class)->value(), 1, ); diff --git a/src/Drivers/Imagick/Encoders/PngEncoder.php b/src/Drivers/Imagick/Encoders/PngEncoder.php index c3889b18..8dd89dac 100644 --- a/src/Drivers/Imagick/Encoders/PngEncoder.php +++ b/src/Drivers/Imagick/Encoders/PngEncoder.php @@ -50,7 +50,7 @@ private function prepareOutput(ImageInterface $image): Imagick if ($this->indexed === false) { $output = clone $image->core()->native(); - // ensure to encode PNG image type 6 true color alpha + // ensure to encode PNG image type 6 (true color alpha) $output->setFormat('PNG32'); $output->setImageFormat('PNG32'); From 839bc6a3c671ab30de3e5c258afa0775975de976 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Mon, 5 Aug 2024 16:38:16 +0200 Subject: [PATCH 09/23] 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 @@ public static function cloneEmpty( 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 10/23] 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 @@ public function testCloneEmpty(): void ); } - 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 11/23] 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 12/23] 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 568444c939dc4f47545d2ebd7e11643aa0054fd4 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 11:19:47 +0200 Subject: [PATCH 13/23] Change logic of encoding indexed PNG format --- src/Drivers/Imagick/Encoders/PngEncoder.php | 41 +++++++++------------ 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/Drivers/Imagick/Encoders/PngEncoder.php b/src/Drivers/Imagick/Encoders/PngEncoder.php index 8dd89dac..8b0fe7ab 100644 --- a/src/Drivers/Imagick/Encoders/PngEncoder.php +++ b/src/Drivers/Imagick/Encoders/PngEncoder.php @@ -47,36 +47,31 @@ public function encode(ImageInterface $image): EncodedImage */ private function prepareOutput(ImageInterface $image): Imagick { - if ($this->indexed === false) { - $output = clone $image->core()->native(); + $output = clone $image; - // ensure to encode PNG image type 6 (true color alpha) - $output->setFormat('PNG32'); - $output->setImageFormat('PNG32'); + if ($this->indexed) { + // reduce colors + $output->reduceColors(256); - return $output; - } + $output = $output->core()->native(); - // get blending color - $blendingColor = $this->driver()->colorProcessor($image->colorspace())->colorToNative( - $this->driver()->handleInput($this->driver()->config()->blendingColor) - ); + $output->setFormat('PNG'); + $output->setImageFormat('PNG'); - // create new image with blending color as background - $output = new Imagick(); - $output->newImage($image->width(), $image->height(), $blendingColor, 'PNG'); + // $output->setImageBackgroundColor(new \ImagickPixel('#00ff00')); + // $output->setImageProperty(); - // set transparency of original image - $output->compositeImage($image->core()->native(), Imagick::COMPOSITE_DSTIN, 0, 0); - $output->transparentPaintImage('#000000', 0, 0, false); + // $output->setType(Imagick::IMGTYPE_PALETTEMATTE); + // $output->setOption('png:bit-depth', '8'); + // $output->setOption('png:color-type', '4'); - // copy original and create indexed color palette version - $output->compositeImage($image->core()->native(), Imagick::COMPOSITE_DEFAULT, 0, 0); - $output->quantizeImage(255, $output->getImageColorSpace(), 0, false, false); + return $output; + } - // ensure to encode PNG image type 3 (indexed) - $output->setFormat('PNG8'); - $output->setImageFormat('PNG8'); + // ensure to encode PNG image type 6 (true color alpha) + $output = clone $image->core()->native(); + $output->setFormat('PNG32'); + $output->setImageFormat('PNG32'); return $output; } From 6196ff1eb946875f3ba4e490a60ba5b6d9aa02d4 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 11:38:33 +0200 Subject: [PATCH 14/23] 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 @@ 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 @@ public function decode(mixed $input): ImageInterface|ColorInterface $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 15/23] 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 @@ public function isTransparent(): bool { 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 @@ public function isTransparent(): bool { 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 @@ public function isTransparent(): bool { 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 @@ public function isTransparent(): bool { 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 @@ public function isGreyscale(): bool; * @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 @@ public function testIsTransparent(): void $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 @@ public function testIsTransparent(): void $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 @@ public function testIsTransparent(): void $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 @@ public function testIsTransparent(): void $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 16/23] 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\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 17/23] 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 @@ 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 @@ public static function cloneEmpty( 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; } From 78534a3b0c57efcc0cb09d5203450427377da3bd Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 13:24:31 +0200 Subject: [PATCH 18/23] Let gd's PngEncoder encode binary transparency in indexed mode --- src/Drivers/Gd/Encoders/PngEncoder.php | 41 ++++---------------------- 1 file changed, 6 insertions(+), 35 deletions(-) diff --git a/src/Drivers/Gd/Encoders/PngEncoder.php b/src/Drivers/Gd/Encoders/PngEncoder.php index 0c3f810b..ebd2d50d 100644 --- a/src/Drivers/Gd/Encoders/PngEncoder.php +++ b/src/Drivers/Gd/Encoders/PngEncoder.php @@ -5,9 +5,6 @@ namespace Intervention\Image\Drivers\Gd\Encoders; use GdImage; -use Intervention\Image\Colors\Rgb\Channels\Blue; -use Intervention\Image\Colors\Rgb\Channels\Green; -use Intervention\Image\Colors\Rgb\Channels\Red; use Intervention\Image\Drivers\Gd\Cloner; use Intervention\Image\EncodedImage; use Intervention\Image\Encoders\PngEncoder as GenericPngEncoder; @@ -48,39 +45,13 @@ public function encode(ImageInterface $image): EncodedImage */ private function prepareOutput(ImageInterface $image): GdImage { - if ($this->indexed === false) { - return Cloner::clone($image->core()->native()); - } - - // clone output instance - $output = Cloner::cloneEmpty($image->core()->native()); - - // Decode configured blending color - $blendingColor = $image->blendingColor(); - - // allocate blending color with slighty different alpha value - // to avoid "overwriting" pixels with the same color in the - // original image with transprency - $blendingIndex = imagecolorallocatealpha( - $output, - $blendingColor->channel(Red::class)->value(), - $blendingColor->channel(Green::class)->value(), - $blendingColor->channel(Blue::class)->value(), - 1, - ); + if ($this->indexed) { + $output = clone $image; + $output->reduceColors(255); - // fill with blending color - imagefill($output, 0, 0, $blendingIndex); - - // define blending index as transparent - imagecolortransparent($output, $blendingIndex); - - // copy original into output - imagecopy($output, $image->core()->native(), 0, 0, 0, 0, imagesx($output), imagesy($output)); - - // reduce to indexed color palette - imagetruecolortopalette($output, true, 255); + return $output->core()->native(); + } - return $output; + return Cloner::clone($image->core()->native()); } } From e7554ec04828a565a0c6b9dec99fe6fad6742293 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 13:27:46 +0200 Subject: [PATCH 19/23] Allow png results to be 'grayscale' with 'indexed' option --- tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php b/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php index b905bd28..d4908fac 100644 --- a/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php +++ b/tests/Unit/Drivers/Imagick/Encoders/PngEncoderTest.php @@ -59,6 +59,12 @@ public static function indexedDataProvider(): array new PngEncoder(indexed: true), 'indexed', ], + + [ + static::createTestImage(3, 2)->fill('ccc'), // new grayscale + new PngEncoder(indexed: true), + 'grayscale', // result should be 'indexed' but there seems to be no way to force this with imagick + ], [ static::readTestImage('circle.png'), // truecolor-alpha new PngEncoder(indexed: false), @@ -67,7 +73,7 @@ public static function indexedDataProvider(): array [ static::readTestImage('circle.png'), // indexedcolor-alpha new PngEncoder(indexed: true), - 'indexed', + 'grayscale-alpha', // result should be 'indexed' but there seems to be no way to force this with imagick ], [ static::readTestImage('tile.png'), // indexed From 9deb50b0bce2ac7d65addeb67040514d517bb25b Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 13:41:19 +0200 Subject: [PATCH 20/23] Change colorspace adjustment logic --- .../Imagick/Decoders/NativeObjectDecoder.php | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php b/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php index 0799b92e..48e50b4b 100644 --- a/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php +++ b/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php @@ -17,13 +17,6 @@ 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)) { @@ -41,10 +34,10 @@ public function decode(mixed $input): ImageInterface|ColorInterface $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)) { + // turn images with colorspace 'GRAY' into 'SRGB' to avoid working on + // greyscale colorspace images as this results images loosing color + // information when placed into this image. + if ($input->getImageColorspace() == Imagick::COLORSPACE_GRAY) { $input->setImageColorspace(Imagick::COLORSPACE_SRGB); } From 32548d033228cc6825ca4e47c274b814c18c06f0 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 13:52:46 +0200 Subject: [PATCH 21/23] Add tested support for PHP 8.4 (#1321) --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 22223f70..7fdf0fbd 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.1', '8.2', '8.3' ] + php: [ '8.1', '8.2', '8.3', '8.4' ] imagemagick: [ '6.9.12-55', '7.1.1-32' ] imagick: [ '3.7.0' ] stability: [ prefer-stable ] From 706ca2c31d2bd8adefb842cccd767d093183edf4 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 16:05:16 +0200 Subject: [PATCH 22/23] Remove test code --- src/Drivers/Imagick/Encoders/PngEncoder.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Drivers/Imagick/Encoders/PngEncoder.php b/src/Drivers/Imagick/Encoders/PngEncoder.php index 8b0fe7ab..91185af0 100644 --- a/src/Drivers/Imagick/Encoders/PngEncoder.php +++ b/src/Drivers/Imagick/Encoders/PngEncoder.php @@ -58,13 +58,6 @@ private function prepareOutput(ImageInterface $image): Imagick $output->setFormat('PNG'); $output->setImageFormat('PNG'); - // $output->setImageBackgroundColor(new \ImagickPixel('#00ff00')); - // $output->setImageProperty(); - - // $output->setType(Imagick::IMGTYPE_PALETTEMATTE); - // $output->setOption('png:bit-depth', '8'); - // $output->setOption('png:color-type', '4'); - return $output; } From 54aa51efda8b9f6d6d3d82c7c35a52fa681d3837 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 11 Aug 2024 17:13:33 +0200 Subject: [PATCH 23/23] Add missing doc blocks --- src/Colors/Hsl/Color.php | 8 ++++++++ src/Colors/Hsv/Color.php | 8 ++++++++ .../Rgb/Decoders/TransparentColorDecoder.php | 5 +++++ src/Drivers/Gd/Analyzers/ColorspaceAnalyzer.php | 5 +++++ src/Drivers/Gd/Analyzers/HeightAnalyzer.php | 5 +++++ src/Drivers/Gd/Analyzers/PixelColorAnalyzer.php | 5 +++++ src/Drivers/Gd/Analyzers/PixelColorsAnalyzer.php | 5 +++++ src/Drivers/Gd/Analyzers/ResolutionAnalyzer.php | 5 +++++ src/Drivers/Gd/Analyzers/WidthAnalyzer.php | 5 +++++ src/Drivers/Gd/ColorProcessor.php | 16 ++++++++++++++++ src/Drivers/Gd/Decoders/Base64ImageDecoder.php | 5 +++++ src/Drivers/Gd/Decoders/DataUriImageDecoder.php | 5 +++++ src/Drivers/Gd/Decoders/FilePathImageDecoder.php | 5 +++++ .../Gd/Decoders/FilePointerImageDecoder.php | 5 +++++ .../Gd/Decoders/SplFileInfoImageDecoder.php | 5 +++++ src/Drivers/Gd/Encoders/AvifEncoder.php | 5 +++++ src/Drivers/Gd/Encoders/BmpEncoder.php | 5 +++++ src/Drivers/Gd/Encoders/GifEncoder.php | 5 +++++ src/Drivers/Gd/Encoders/JpegEncoder.php | 5 +++++ src/Drivers/Gd/Encoders/WebpEncoder.php | 5 +++++ .../Gd/Modifiers/AlignRotationModifier.php | 5 +++++ .../Gd/Modifiers/BlendTransparencyModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/BlurModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/BrightnessModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/ColorizeModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/ColorspaceModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/ContainModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/ContrastModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/CoverModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/CropModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/DrawBezierModifier.php | 3 +++ src/Drivers/Gd/Modifiers/DrawEllipseModifier.php | 3 +++ src/Drivers/Gd/Modifiers/DrawPixelModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/DrawPolygonModifier.php | 3 +++ .../Gd/Modifiers/DrawRectangleModifier.php | 3 +++ src/Drivers/Gd/Modifiers/FillModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/FlipModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/FlopModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/GammaModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/GreyscaleModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/InvertModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/PixelateModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/PlaceModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/ProfileModifier.php | 5 +++++ .../Gd/Modifiers/ProfileRemovalModifier.php | 5 +++++ .../Gd/Modifiers/QuantizeColorsModifier.php | 5 +++++ .../Gd/Modifiers/RemoveAnimationModifier.php | 5 +++++ .../Gd/Modifiers/ResizeCanvasModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/ResizeModifier.php | 11 +++++++++++ src/Drivers/Gd/Modifiers/ResolutionModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/RotateModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/ScaleDownModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/SharpenModifier.php | 5 +++++ .../Gd/Modifiers/SliceAnimationModifier.php | 5 +++++ src/Drivers/Gd/Modifiers/TrimModifier.php | 5 +++++ .../Imagick/Decoders/Base64ImageDecoder.php | 5 +++++ .../Imagick/Decoders/BinaryImageDecoder.php | 5 +++++ .../Imagick/Decoders/DataUriImageDecoder.php | 5 +++++ .../Imagick/Decoders/FilePathImageDecoder.php | 5 +++++ .../Imagick/Decoders/FilePointerImageDecoder.php | 5 +++++ .../Imagick/Decoders/NativeObjectDecoder.php | 5 +++++ .../Imagick/Decoders/SplFileInfoImageDecoder.php | 5 +++++ src/Drivers/Imagick/Frame.php | 8 ++++++++ src/Drivers/SpecializableDecoder.php | 5 +++++ src/Encoders/AvifEncoder.php | 6 ++++++ src/Encoders/GifEncoder.php | 6 ++++++ src/Encoders/HeicEncoder.php | 6 ++++++ src/Encoders/Jpeg2000Encoder.php | 6 ++++++ src/Encoders/JpegEncoder.php | 7 +++++++ src/Encoders/PngEncoder.php | 7 +++++++ src/Encoders/TiffEncoder.php | 6 ++++++ src/Encoders/WebpEncoder.php | 6 ++++++ src/Interfaces/ProfileInterface.php | 5 +++++ src/Modifiers/BlendTransparencyModifier.php | 6 ++++++ src/Modifiers/ColorizeModifier.php | 8 ++++++++ src/Modifiers/ContrastModifier.php | 6 ++++++ src/Modifiers/CoverModifier.php | 8 ++++++++ src/Modifiers/CropModifier.php | 11 +++++++++++ src/Modifiers/DrawBezierModifier.php | 11 +++++++++++ src/Modifiers/DrawLineModifier.php | 11 +++++++++++ src/Modifiers/DrawPixelModifier.php | 7 +++++++ src/Modifiers/DrawRectangleModifier.php | 11 +++++++++++ src/Modifiers/PlaceModifier.php | 10 ++++++++++ src/Modifiers/QuantizeColorsModifier.php | 7 +++++++ src/Modifiers/ResizeCanvasModifier.php | 9 +++++++++ src/Modifiers/ResizeModifier.php | 7 +++++++ src/Modifiers/ResolutionModifier.php | 7 +++++++ src/Modifiers/TextModifier.php | 8 ++++++++ src/Modifiers/TrimModifier.php | 6 ++++++ src/Typography/TextBlock.php | 6 ++++++ 90 files changed, 532 insertions(+) diff --git a/src/Colors/Hsl/Color.php b/src/Colors/Hsl/Color.php index 20ca0e5d..ad03c6cc 100644 --- a/src/Colors/Hsl/Color.php +++ b/src/Colors/Hsl/Color.php @@ -16,6 +16,14 @@ class Color extends AbstractColor { + /** + * Create new color object + * + * @param int $h + * @param int $s + * @param int $l + * @return void + */ public function __construct(int $h, int $s, int $l) { /** @throws void */ diff --git a/src/Colors/Hsv/Color.php b/src/Colors/Hsv/Color.php index 8a4f18b2..62893ec0 100644 --- a/src/Colors/Hsv/Color.php +++ b/src/Colors/Hsv/Color.php @@ -16,6 +16,14 @@ class Color extends AbstractColor { + /** + * Create new color object + * + * @param int $h + * @param int $s + * @param int $v + * @return void + */ public function __construct(int $h, int $s, int $v) { /** @throws void */ diff --git a/src/Colors/Rgb/Decoders/TransparentColorDecoder.php b/src/Colors/Rgb/Decoders/TransparentColorDecoder.php index c3823d74..f818b790 100644 --- a/src/Colors/Rgb/Decoders/TransparentColorDecoder.php +++ b/src/Colors/Rgb/Decoders/TransparentColorDecoder.php @@ -10,6 +10,11 @@ class TransparentColorDecoder extends HexColorDecoder { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!is_string($input)) { diff --git a/src/Drivers/Gd/Analyzers/ColorspaceAnalyzer.php b/src/Drivers/Gd/Analyzers/ColorspaceAnalyzer.php index b1082cfd..73057f72 100644 --- a/src/Drivers/Gd/Analyzers/ColorspaceAnalyzer.php +++ b/src/Drivers/Gd/Analyzers/ColorspaceAnalyzer.php @@ -11,6 +11,11 @@ class ColorspaceAnalyzer extends GenericColorspaceAnalyzer implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see AnalyzerInterface::analyze() + */ public function analyze(ImageInterface $image): mixed { return new Colorspace(); diff --git a/src/Drivers/Gd/Analyzers/HeightAnalyzer.php b/src/Drivers/Gd/Analyzers/HeightAnalyzer.php index 40ffb9bc..cf8ed31b 100644 --- a/src/Drivers/Gd/Analyzers/HeightAnalyzer.php +++ b/src/Drivers/Gd/Analyzers/HeightAnalyzer.php @@ -10,6 +10,11 @@ class HeightAnalyzer extends GenericHeightAnalyzer implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see AnalyzerInterface::analyze() + */ public function analyze(ImageInterface $image): mixed { return imagesy($image->core()->native()); diff --git a/src/Drivers/Gd/Analyzers/PixelColorAnalyzer.php b/src/Drivers/Gd/Analyzers/PixelColorAnalyzer.php index 60a0f7fc..b27583a3 100644 --- a/src/Drivers/Gd/Analyzers/PixelColorAnalyzer.php +++ b/src/Drivers/Gd/Analyzers/PixelColorAnalyzer.php @@ -15,6 +15,11 @@ class PixelColorAnalyzer extends GenericPixelColorAnalyzer implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see AnalyzerInterface::analyze() + */ public function analyze(ImageInterface $image): mixed { return $this->colorAt( diff --git a/src/Drivers/Gd/Analyzers/PixelColorsAnalyzer.php b/src/Drivers/Gd/Analyzers/PixelColorsAnalyzer.php index 41d7135a..862d41e1 100644 --- a/src/Drivers/Gd/Analyzers/PixelColorsAnalyzer.php +++ b/src/Drivers/Gd/Analyzers/PixelColorsAnalyzer.php @@ -9,6 +9,11 @@ class PixelColorsAnalyzer extends PixelColorAnalyzer { + /** + * {@inheritdoc} + * + * @see AnalyzerInterface::analyze() + */ public function analyze(ImageInterface $image): mixed { $colors = new Collection(); diff --git a/src/Drivers/Gd/Analyzers/ResolutionAnalyzer.php b/src/Drivers/Gd/Analyzers/ResolutionAnalyzer.php index 21ed0306..93d37f24 100644 --- a/src/Drivers/Gd/Analyzers/ResolutionAnalyzer.php +++ b/src/Drivers/Gd/Analyzers/ResolutionAnalyzer.php @@ -11,6 +11,11 @@ class ResolutionAnalyzer extends GenericResolutionAnalyzer implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see AnalyzerInterface::analyze() + */ public function analyze(ImageInterface $image): mixed { return new Resolution(...imageresolution($image->core()->native())); diff --git a/src/Drivers/Gd/Analyzers/WidthAnalyzer.php b/src/Drivers/Gd/Analyzers/WidthAnalyzer.php index b57a7e14..9c6b793b 100644 --- a/src/Drivers/Gd/Analyzers/WidthAnalyzer.php +++ b/src/Drivers/Gd/Analyzers/WidthAnalyzer.php @@ -10,6 +10,11 @@ class WidthAnalyzer extends GenericWidthAnalyzer implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see AnalyzerInterface::analyze() + */ public function analyze(ImageInterface $image): mixed { return imagesx($image->core()->native()); diff --git a/src/Drivers/Gd/ColorProcessor.php b/src/Drivers/Gd/ColorProcessor.php index c2660340..30583739 100644 --- a/src/Drivers/Gd/ColorProcessor.php +++ b/src/Drivers/Gd/ColorProcessor.php @@ -17,10 +17,21 @@ class ColorProcessor implements ColorProcessorInterface { + /** + * Create new color processor object + * + * @param ColorspaceInterface $colorspace + * @return void + */ public function __construct(protected ColorspaceInterface $colorspace = new Colorspace()) { } + /** + * {@inheritdoc} + * + * @see ColorProcessorInterface::colorToNative() + */ public function colorToNative(ColorInterface $color): int { // convert color to colorspace @@ -39,6 +50,11 @@ public function colorToNative(ColorInterface $color): int return ($a << 24) + ($r << 16) + ($g << 8) + $b; } + /** + * {@inheritdoc} + * + * @see ColorProcessorInterface::nativeToColor() + */ public function nativeToColor(mixed $value): ColorInterface { if (!is_int($value)) { diff --git a/src/Drivers/Gd/Decoders/Base64ImageDecoder.php b/src/Drivers/Gd/Decoders/Base64ImageDecoder.php index f8970b65..7b3686ad 100644 --- a/src/Drivers/Gd/Decoders/Base64ImageDecoder.php +++ b/src/Drivers/Gd/Decoders/Base64ImageDecoder.php @@ -11,6 +11,11 @@ class Base64ImageDecoder extends BinaryImageDecoder implements DecoderInterface { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!$this->isValidBase64($input)) { diff --git a/src/Drivers/Gd/Decoders/DataUriImageDecoder.php b/src/Drivers/Gd/Decoders/DataUriImageDecoder.php index 939b1e0e..fe3abe6f 100644 --- a/src/Drivers/Gd/Decoders/DataUriImageDecoder.php +++ b/src/Drivers/Gd/Decoders/DataUriImageDecoder.php @@ -11,6 +11,11 @@ class DataUriImageDecoder extends BinaryImageDecoder implements DecoderInterface { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!is_string($input)) { diff --git a/src/Drivers/Gd/Decoders/FilePathImageDecoder.php b/src/Drivers/Gd/Decoders/FilePathImageDecoder.php index 59b984f7..bb6ddd5c 100644 --- a/src/Drivers/Gd/Decoders/FilePathImageDecoder.php +++ b/src/Drivers/Gd/Decoders/FilePathImageDecoder.php @@ -13,6 +13,11 @@ class FilePathImageDecoder extends NativeObjectDecoder implements DecoderInterface { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!$this->isFile($input)) { diff --git a/src/Drivers/Gd/Decoders/FilePointerImageDecoder.php b/src/Drivers/Gd/Decoders/FilePointerImageDecoder.php index 66a39f01..0bf649dc 100644 --- a/src/Drivers/Gd/Decoders/FilePointerImageDecoder.php +++ b/src/Drivers/Gd/Decoders/FilePointerImageDecoder.php @@ -10,6 +10,11 @@ class FilePointerImageDecoder extends BinaryImageDecoder { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!is_resource($input) || !in_array(get_resource_type($input), ['file', 'stream'])) { diff --git a/src/Drivers/Gd/Decoders/SplFileInfoImageDecoder.php b/src/Drivers/Gd/Decoders/SplFileInfoImageDecoder.php index 7febefb0..7aee8f58 100644 --- a/src/Drivers/Gd/Decoders/SplFileInfoImageDecoder.php +++ b/src/Drivers/Gd/Decoders/SplFileInfoImageDecoder.php @@ -12,6 +12,11 @@ class SplFileInfoImageDecoder extends FilePathImageDecoder implements DecoderInterface { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!is_a($input, SplFileInfo::class)) { diff --git a/src/Drivers/Gd/Encoders/AvifEncoder.php b/src/Drivers/Gd/Encoders/AvifEncoder.php index cc590873..87e5d9e4 100644 --- a/src/Drivers/Gd/Encoders/AvifEncoder.php +++ b/src/Drivers/Gd/Encoders/AvifEncoder.php @@ -11,6 +11,11 @@ class AvifEncoder extends GenericAvifEncoder implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see EncoderInterface::encode() + */ public function encode(ImageInterface $image): EncodedImage { $gd = $image->core()->native(); diff --git a/src/Drivers/Gd/Encoders/BmpEncoder.php b/src/Drivers/Gd/Encoders/BmpEncoder.php index 811cb93e..4cf0dbfa 100644 --- a/src/Drivers/Gd/Encoders/BmpEncoder.php +++ b/src/Drivers/Gd/Encoders/BmpEncoder.php @@ -11,6 +11,11 @@ class BmpEncoder extends GenericBmpEncoder implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see EncoderInterface::encode() + */ public function encode(ImageInterface $image): EncodedImage { $data = $this->buffered(function () use ($image) { diff --git a/src/Drivers/Gd/Encoders/GifEncoder.php b/src/Drivers/Gd/Encoders/GifEncoder.php index 1031a528..875df787 100644 --- a/src/Drivers/Gd/Encoders/GifEncoder.php +++ b/src/Drivers/Gd/Encoders/GifEncoder.php @@ -15,6 +15,11 @@ class GifEncoder extends GenericGifEncoder implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see EncoderInterface::encode() + */ public function encode(ImageInterface $image): EncodedImage { if ($image->isAnimated()) { diff --git a/src/Drivers/Gd/Encoders/JpegEncoder.php b/src/Drivers/Gd/Encoders/JpegEncoder.php index b408a197..268a6f4b 100644 --- a/src/Drivers/Gd/Encoders/JpegEncoder.php +++ b/src/Drivers/Gd/Encoders/JpegEncoder.php @@ -12,6 +12,11 @@ class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see EncoderInterface::encode() + */ public function encode(ImageInterface $image): EncodedImage { $blendingColor = $this->driver()->handleInput( diff --git a/src/Drivers/Gd/Encoders/WebpEncoder.php b/src/Drivers/Gd/Encoders/WebpEncoder.php index 5a838c76..5e06ab48 100644 --- a/src/Drivers/Gd/Encoders/WebpEncoder.php +++ b/src/Drivers/Gd/Encoders/WebpEncoder.php @@ -11,6 +11,11 @@ class WebpEncoder extends GenericWebpEncoder implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see EncoderInterface::encode() + */ public function encode(ImageInterface $image): EncodedImage { $quality = $this->quality === 100 ? IMG_WEBP_LOSSLESS : $this->quality; diff --git a/src/Drivers/Gd/Modifiers/AlignRotationModifier.php b/src/Drivers/Gd/Modifiers/AlignRotationModifier.php index daf152fb..791ae7db 100644 --- a/src/Drivers/Gd/Modifiers/AlignRotationModifier.php +++ b/src/Drivers/Gd/Modifiers/AlignRotationModifier.php @@ -10,6 +10,11 @@ class AlignRotationModifier extends GenericAlignRotationModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $image = match ($image->exif('IFD0.Orientation')) { diff --git a/src/Drivers/Gd/Modifiers/BlendTransparencyModifier.php b/src/Drivers/Gd/Modifiers/BlendTransparencyModifier.php index c2cec921..555a163f 100644 --- a/src/Drivers/Gd/Modifiers/BlendTransparencyModifier.php +++ b/src/Drivers/Gd/Modifiers/BlendTransparencyModifier.php @@ -11,6 +11,11 @@ class BlendTransparencyModifier extends GenericBlendTransparencyModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { // decode blending color diff --git a/src/Drivers/Gd/Modifiers/BlurModifier.php b/src/Drivers/Gd/Modifiers/BlurModifier.php index 5357c40e..14fe41a4 100644 --- a/src/Drivers/Gd/Modifiers/BlurModifier.php +++ b/src/Drivers/Gd/Modifiers/BlurModifier.php @@ -10,6 +10,11 @@ class BlurModifier extends GenericBlurModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { foreach ($image as $frame) { diff --git a/src/Drivers/Gd/Modifiers/BrightnessModifier.php b/src/Drivers/Gd/Modifiers/BrightnessModifier.php index 747d51d6..022c679a 100644 --- a/src/Drivers/Gd/Modifiers/BrightnessModifier.php +++ b/src/Drivers/Gd/Modifiers/BrightnessModifier.php @@ -10,6 +10,11 @@ class BrightnessModifier extends GenericBrightnessModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { foreach ($image as $frame) { diff --git a/src/Drivers/Gd/Modifiers/ColorizeModifier.php b/src/Drivers/Gd/Modifiers/ColorizeModifier.php index 4458a553..c753e438 100644 --- a/src/Drivers/Gd/Modifiers/ColorizeModifier.php +++ b/src/Drivers/Gd/Modifiers/ColorizeModifier.php @@ -10,6 +10,11 @@ class ColorizeModifier extends GenericColorizeModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { // normalize colorize levels diff --git a/src/Drivers/Gd/Modifiers/ColorspaceModifier.php b/src/Drivers/Gd/Modifiers/ColorspaceModifier.php index 748ebc7a..a94f82dd 100644 --- a/src/Drivers/Gd/Modifiers/ColorspaceModifier.php +++ b/src/Drivers/Gd/Modifiers/ColorspaceModifier.php @@ -12,6 +12,11 @@ class ColorspaceModifier extends GenericColorspaceModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { if (!is_a($this->targetColorspace(), RgbColorspace::class)) { diff --git a/src/Drivers/Gd/Modifiers/ContainModifier.php b/src/Drivers/Gd/Modifiers/ContainModifier.php index 8761111e..8462e8ef 100644 --- a/src/Drivers/Gd/Modifiers/ContainModifier.php +++ b/src/Drivers/Gd/Modifiers/ContainModifier.php @@ -18,6 +18,11 @@ class ContainModifier extends GenericContainModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $crop = $this->getCropSize($image); diff --git a/src/Drivers/Gd/Modifiers/ContrastModifier.php b/src/Drivers/Gd/Modifiers/ContrastModifier.php index 8567ac35..7a0ac6b8 100644 --- a/src/Drivers/Gd/Modifiers/ContrastModifier.php +++ b/src/Drivers/Gd/Modifiers/ContrastModifier.php @@ -10,6 +10,11 @@ class ContrastModifier extends GenericContrastModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { foreach ($image as $frame) { diff --git a/src/Drivers/Gd/Modifiers/CoverModifier.php b/src/Drivers/Gd/Modifiers/CoverModifier.php index 4343d43d..e676e663 100644 --- a/src/Drivers/Gd/Modifiers/CoverModifier.php +++ b/src/Drivers/Gd/Modifiers/CoverModifier.php @@ -14,6 +14,11 @@ class CoverModifier extends GenericCoverModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $crop = $this->getCropSize($image); diff --git a/src/Drivers/Gd/Modifiers/CropModifier.php b/src/Drivers/Gd/Modifiers/CropModifier.php index 56a019fd..fabdf7f7 100644 --- a/src/Drivers/Gd/Modifiers/CropModifier.php +++ b/src/Drivers/Gd/Modifiers/CropModifier.php @@ -14,6 +14,11 @@ class CropModifier extends GenericCropModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $originalSize = $image->size(); diff --git a/src/Drivers/Gd/Modifiers/DrawBezierModifier.php b/src/Drivers/Gd/Modifiers/DrawBezierModifier.php index a0dfaf91..d8da4937 100644 --- a/src/Drivers/Gd/Modifiers/DrawBezierModifier.php +++ b/src/Drivers/Gd/Modifiers/DrawBezierModifier.php @@ -13,6 +13,9 @@ class DrawBezierModifier extends ModifiersDrawBezierModifier implements SpecializedInterface { /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() * @throws RuntimeException * @throws GeometryException */ diff --git a/src/Drivers/Gd/Modifiers/DrawEllipseModifier.php b/src/Drivers/Gd/Modifiers/DrawEllipseModifier.php index b070349d..2a80af95 100644 --- a/src/Drivers/Gd/Modifiers/DrawEllipseModifier.php +++ b/src/Drivers/Gd/Modifiers/DrawEllipseModifier.php @@ -12,6 +12,9 @@ class DrawEllipseModifier extends GenericDrawEllipseModifier implements SpecializedInterface { /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() * @throws RuntimeException */ public function apply(ImageInterface $image): ImageInterface diff --git a/src/Drivers/Gd/Modifiers/DrawPixelModifier.php b/src/Drivers/Gd/Modifiers/DrawPixelModifier.php index f626ddfb..9fc954cd 100644 --- a/src/Drivers/Gd/Modifiers/DrawPixelModifier.php +++ b/src/Drivers/Gd/Modifiers/DrawPixelModifier.php @@ -10,6 +10,11 @@ class DrawPixelModifier extends GenericDrawPixelModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $color = $this->driver()->colorProcessor($image->colorspace())->colorToNative( diff --git a/src/Drivers/Gd/Modifiers/DrawPolygonModifier.php b/src/Drivers/Gd/Modifiers/DrawPolygonModifier.php index e09fbfc5..55e54272 100644 --- a/src/Drivers/Gd/Modifiers/DrawPolygonModifier.php +++ b/src/Drivers/Gd/Modifiers/DrawPolygonModifier.php @@ -12,6 +12,9 @@ class DrawPolygonModifier extends ModifiersDrawPolygonModifier implements SpecializedInterface { /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() * @throws RuntimeException */ public function apply(ImageInterface $image): ImageInterface diff --git a/src/Drivers/Gd/Modifiers/DrawRectangleModifier.php b/src/Drivers/Gd/Modifiers/DrawRectangleModifier.php index 9b024dbd..2b23c5ee 100644 --- a/src/Drivers/Gd/Modifiers/DrawRectangleModifier.php +++ b/src/Drivers/Gd/Modifiers/DrawRectangleModifier.php @@ -12,6 +12,9 @@ class DrawRectangleModifier extends GenericDrawRectangleModifier implements SpecializedInterface { /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() * @throws RuntimeException */ public function apply(ImageInterface $image): ImageInterface diff --git a/src/Drivers/Gd/Modifiers/FillModifier.php b/src/Drivers/Gd/Modifiers/FillModifier.php index 0fe860fa..412f8059 100644 --- a/src/Drivers/Gd/Modifiers/FillModifier.php +++ b/src/Drivers/Gd/Modifiers/FillModifier.php @@ -12,6 +12,11 @@ class FillModifier extends GenericFillModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $color = $this->color($image); diff --git a/src/Drivers/Gd/Modifiers/FlipModifier.php b/src/Drivers/Gd/Modifiers/FlipModifier.php index 8e832cce..0107200a 100644 --- a/src/Drivers/Gd/Modifiers/FlipModifier.php +++ b/src/Drivers/Gd/Modifiers/FlipModifier.php @@ -10,6 +10,11 @@ class FlipModifier extends GenericFlipModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { foreach ($image as $frame) { diff --git a/src/Drivers/Gd/Modifiers/FlopModifier.php b/src/Drivers/Gd/Modifiers/FlopModifier.php index 238bc264..70331754 100644 --- a/src/Drivers/Gd/Modifiers/FlopModifier.php +++ b/src/Drivers/Gd/Modifiers/FlopModifier.php @@ -10,6 +10,11 @@ class FlopModifier extends GenericFlopModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { foreach ($image as $frame) { diff --git a/src/Drivers/Gd/Modifiers/GammaModifier.php b/src/Drivers/Gd/Modifiers/GammaModifier.php index 0815a7ba..8da6499e 100644 --- a/src/Drivers/Gd/Modifiers/GammaModifier.php +++ b/src/Drivers/Gd/Modifiers/GammaModifier.php @@ -10,6 +10,11 @@ class GammaModifier extends GenericGammaModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { foreach ($image as $frame) { diff --git a/src/Drivers/Gd/Modifiers/GreyscaleModifier.php b/src/Drivers/Gd/Modifiers/GreyscaleModifier.php index 2eb04c23..a1cf280a 100644 --- a/src/Drivers/Gd/Modifiers/GreyscaleModifier.php +++ b/src/Drivers/Gd/Modifiers/GreyscaleModifier.php @@ -10,6 +10,11 @@ class GreyscaleModifier extends GenericGreyscaleModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { foreach ($image as $frame) { diff --git a/src/Drivers/Gd/Modifiers/InvertModifier.php b/src/Drivers/Gd/Modifiers/InvertModifier.php index 65d42b4e..e2c8dc67 100644 --- a/src/Drivers/Gd/Modifiers/InvertModifier.php +++ b/src/Drivers/Gd/Modifiers/InvertModifier.php @@ -10,6 +10,11 @@ class InvertModifier extends GenericInvertModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { foreach ($image as $frame) { diff --git a/src/Drivers/Gd/Modifiers/PixelateModifier.php b/src/Drivers/Gd/Modifiers/PixelateModifier.php index 06ddde14..ecbe3e58 100644 --- a/src/Drivers/Gd/Modifiers/PixelateModifier.php +++ b/src/Drivers/Gd/Modifiers/PixelateModifier.php @@ -10,6 +10,11 @@ class PixelateModifier extends GenericPixelateModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { foreach ($image as $frame) { diff --git a/src/Drivers/Gd/Modifiers/PlaceModifier.php b/src/Drivers/Gd/Modifiers/PlaceModifier.php index eaad5c2b..9bc264d0 100644 --- a/src/Drivers/Gd/Modifiers/PlaceModifier.php +++ b/src/Drivers/Gd/Modifiers/PlaceModifier.php @@ -13,6 +13,11 @@ class PlaceModifier extends GenericPlaceModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $watermark = $this->driver()->handleInput($this->element); diff --git a/src/Drivers/Gd/Modifiers/ProfileModifier.php b/src/Drivers/Gd/Modifiers/ProfileModifier.php index 5a5310a1..a862395b 100644 --- a/src/Drivers/Gd/Modifiers/ProfileModifier.php +++ b/src/Drivers/Gd/Modifiers/ProfileModifier.php @@ -11,6 +11,11 @@ class ProfileModifier extends GenericProfileModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { throw new NotSupportedException( diff --git a/src/Drivers/Gd/Modifiers/ProfileRemovalModifier.php b/src/Drivers/Gd/Modifiers/ProfileRemovalModifier.php index 1121036a..2960cd5f 100644 --- a/src/Drivers/Gd/Modifiers/ProfileRemovalModifier.php +++ b/src/Drivers/Gd/Modifiers/ProfileRemovalModifier.php @@ -10,6 +10,11 @@ class ProfileRemovalModifier extends GenericProfileRemovalModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { // Color profiles are not supported by GD, so the decoded diff --git a/src/Drivers/Gd/Modifiers/QuantizeColorsModifier.php b/src/Drivers/Gd/Modifiers/QuantizeColorsModifier.php index 36e25496..60307844 100644 --- a/src/Drivers/Gd/Modifiers/QuantizeColorsModifier.php +++ b/src/Drivers/Gd/Modifiers/QuantizeColorsModifier.php @@ -12,6 +12,11 @@ class QuantizeColorsModifier extends GenericQuantizeColorsModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { if ($this->limit <= 0) { diff --git a/src/Drivers/Gd/Modifiers/RemoveAnimationModifier.php b/src/Drivers/Gd/Modifiers/RemoveAnimationModifier.php index 345798f9..6160cab4 100644 --- a/src/Drivers/Gd/Modifiers/RemoveAnimationModifier.php +++ b/src/Drivers/Gd/Modifiers/RemoveAnimationModifier.php @@ -10,6 +10,11 @@ class RemoveAnimationModifier extends GenericRemoveAnimationModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $image->core()->setNative( diff --git a/src/Drivers/Gd/Modifiers/ResizeCanvasModifier.php b/src/Drivers/Gd/Modifiers/ResizeCanvasModifier.php index 458a4fd0..65314783 100644 --- a/src/Drivers/Gd/Modifiers/ResizeCanvasModifier.php +++ b/src/Drivers/Gd/Modifiers/ResizeCanvasModifier.php @@ -18,6 +18,11 @@ class ResizeCanvasModifier extends GenericResizeCanvasModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $resize = $this->cropSize($image); diff --git a/src/Drivers/Gd/Modifiers/ResizeModifier.php b/src/Drivers/Gd/Modifiers/ResizeModifier.php index faf67aaf..3b6663f4 100644 --- a/src/Drivers/Gd/Modifiers/ResizeModifier.php +++ b/src/Drivers/Gd/Modifiers/ResizeModifier.php @@ -6,6 +6,7 @@ use Intervention\Image\Drivers\Gd\Cloner; use Intervention\Image\Exceptions\ColorException; +use Intervention\Image\Exceptions\GeometryException; use Intervention\Image\Exceptions\RuntimeException; use Intervention\Image\Interfaces\FrameInterface; use Intervention\Image\Interfaces\ImageInterface; @@ -15,6 +16,11 @@ class ResizeModifier extends GenericResizeModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $resizeTo = $this->getAdjustedSize($image); @@ -52,7 +58,12 @@ private function resizeFrame(FrameInterface $frame, SizeInterface $resizeTo): vo } /** + * Return the size the modifier will resize to + * + * @param ImageInterface $image * @throws RuntimeException + * @throws GeometryException + * @return SizeInterface */ protected function getAdjustedSize(ImageInterface $image): SizeInterface { diff --git a/src/Drivers/Gd/Modifiers/ResolutionModifier.php b/src/Drivers/Gd/Modifiers/ResolutionModifier.php index 6fcc2335..d6fd504c 100644 --- a/src/Drivers/Gd/Modifiers/ResolutionModifier.php +++ b/src/Drivers/Gd/Modifiers/ResolutionModifier.php @@ -10,6 +10,11 @@ class ResolutionModifier extends GenericResolutionModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $x = intval(round($this->x)); diff --git a/src/Drivers/Gd/Modifiers/RotateModifier.php b/src/Drivers/Gd/Modifiers/RotateModifier.php index 86811268..2fe5e5cf 100644 --- a/src/Drivers/Gd/Modifiers/RotateModifier.php +++ b/src/Drivers/Gd/Modifiers/RotateModifier.php @@ -18,6 +18,11 @@ class RotateModifier extends GenericRotateModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $background = $this->driver()->handleInput($this->background); diff --git a/src/Drivers/Gd/Modifiers/ScaleDownModifier.php b/src/Drivers/Gd/Modifiers/ScaleDownModifier.php index 606978d4..15287e6c 100644 --- a/src/Drivers/Gd/Modifiers/ScaleDownModifier.php +++ b/src/Drivers/Gd/Modifiers/ScaleDownModifier.php @@ -9,6 +9,11 @@ class ScaleDownModifier extends ResizeModifier { + /** + * {@inheritdoc} + * + * @see ResizeModifier::getAdjustedSize() + */ protected function getAdjustedSize(ImageInterface $image): SizeInterface { return $image->size()->scaleDown($this->width, $this->height); diff --git a/src/Drivers/Gd/Modifiers/SharpenModifier.php b/src/Drivers/Gd/Modifiers/SharpenModifier.php index a1c59397..3943d2cb 100644 --- a/src/Drivers/Gd/Modifiers/SharpenModifier.php +++ b/src/Drivers/Gd/Modifiers/SharpenModifier.php @@ -10,6 +10,11 @@ class SharpenModifier extends GenericSharpenModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { $matrix = $this->matrix(); diff --git a/src/Drivers/Gd/Modifiers/SliceAnimationModifier.php b/src/Drivers/Gd/Modifiers/SliceAnimationModifier.php index 84b04c36..8986e7fe 100644 --- a/src/Drivers/Gd/Modifiers/SliceAnimationModifier.php +++ b/src/Drivers/Gd/Modifiers/SliceAnimationModifier.php @@ -11,6 +11,11 @@ class SliceAnimationModifier extends GenericSliceAnimationModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { if ($this->offset >= $image->count()) { diff --git a/src/Drivers/Gd/Modifiers/TrimModifier.php b/src/Drivers/Gd/Modifiers/TrimModifier.php index 7c011e0d..26be5d9e 100644 --- a/src/Drivers/Gd/Modifiers/TrimModifier.php +++ b/src/Drivers/Gd/Modifiers/TrimModifier.php @@ -14,6 +14,11 @@ class TrimModifier extends GenericTrimModifier implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see ModifierInterface::apply() + */ public function apply(ImageInterface $image): ImageInterface { if ($image->isAnimated()) { diff --git a/src/Drivers/Imagick/Decoders/Base64ImageDecoder.php b/src/Drivers/Imagick/Decoders/Base64ImageDecoder.php index ecddde3c..03fd07ba 100644 --- a/src/Drivers/Imagick/Decoders/Base64ImageDecoder.php +++ b/src/Drivers/Imagick/Decoders/Base64ImageDecoder.php @@ -10,6 +10,11 @@ class Base64ImageDecoder extends BinaryImageDecoder { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!$this->isValidBase64($input)) { diff --git a/src/Drivers/Imagick/Decoders/BinaryImageDecoder.php b/src/Drivers/Imagick/Decoders/BinaryImageDecoder.php index 25dc5ee3..96850b3c 100644 --- a/src/Drivers/Imagick/Decoders/BinaryImageDecoder.php +++ b/src/Drivers/Imagick/Decoders/BinaryImageDecoder.php @@ -13,6 +13,11 @@ class BinaryImageDecoder extends NativeObjectDecoder { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!is_string($input)) { diff --git a/src/Drivers/Imagick/Decoders/DataUriImageDecoder.php b/src/Drivers/Imagick/Decoders/DataUriImageDecoder.php index 82a39e68..f395cb00 100644 --- a/src/Drivers/Imagick/Decoders/DataUriImageDecoder.php +++ b/src/Drivers/Imagick/Decoders/DataUriImageDecoder.php @@ -10,6 +10,11 @@ class DataUriImageDecoder extends BinaryImageDecoder { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!is_string($input)) { diff --git a/src/Drivers/Imagick/Decoders/FilePathImageDecoder.php b/src/Drivers/Imagick/Decoders/FilePathImageDecoder.php index 4a8d4e11..a418099c 100644 --- a/src/Drivers/Imagick/Decoders/FilePathImageDecoder.php +++ b/src/Drivers/Imagick/Decoders/FilePathImageDecoder.php @@ -12,6 +12,11 @@ class FilePathImageDecoder extends NativeObjectDecoder { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!$this->isFile($input)) { diff --git a/src/Drivers/Imagick/Decoders/FilePointerImageDecoder.php b/src/Drivers/Imagick/Decoders/FilePointerImageDecoder.php index 3145a2b7..08717e09 100644 --- a/src/Drivers/Imagick/Decoders/FilePointerImageDecoder.php +++ b/src/Drivers/Imagick/Decoders/FilePointerImageDecoder.php @@ -10,6 +10,11 @@ class FilePointerImageDecoder extends BinaryImageDecoder { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!is_resource($input) || !in_array(get_resource_type($input), ['file', 'stream'])) { diff --git a/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php b/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php index 48e50b4b..dec2d8fd 100644 --- a/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php +++ b/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php @@ -17,6 +17,11 @@ class NativeObjectDecoder extends SpecializableDecoder implements SpecializedInterface { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!is_object($input)) { diff --git a/src/Drivers/Imagick/Decoders/SplFileInfoImageDecoder.php b/src/Drivers/Imagick/Decoders/SplFileInfoImageDecoder.php index ad96b7ce..8850123e 100644 --- a/src/Drivers/Imagick/Decoders/SplFileInfoImageDecoder.php +++ b/src/Drivers/Imagick/Decoders/SplFileInfoImageDecoder.php @@ -11,6 +11,11 @@ class SplFileInfoImageDecoder extends FilePathImageDecoder { + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { if (!is_a($input, SplFileInfo::class)) { diff --git a/src/Drivers/Imagick/Frame.php b/src/Drivers/Imagick/Frame.php index 2439c855..354504cf 100644 --- a/src/Drivers/Imagick/Frame.php +++ b/src/Drivers/Imagick/Frame.php @@ -5,6 +5,7 @@ namespace Intervention\Image\Drivers\Imagick; use Imagick; +use ImagickException; use ImagickPixel; use Intervention\Image\Geometry\Rectangle; use Intervention\Image\Image; @@ -15,6 +16,13 @@ class Frame implements FrameInterface { + /** + * Create new frame object + * + * @param Imagick $native + * @throws ImagickException + * @return void + */ public function __construct(protected Imagick $native) { $background = new ImagickPixel('rgba(255, 255, 255, 0)'); diff --git a/src/Drivers/SpecializableDecoder.php b/src/Drivers/SpecializableDecoder.php index 8a9916f6..9b0bf8bc 100644 --- a/src/Drivers/SpecializableDecoder.php +++ b/src/Drivers/SpecializableDecoder.php @@ -14,6 +14,11 @@ abstract class SpecializableDecoder extends AbstractDecoder implements Specializ { use CanBeDriverSpecialized; + /** + * {@inheritdoc} + * + * @see DecoderInterface::decode() + */ public function decode(mixed $input): ImageInterface|ColorInterface { throw new DecoderException('Decoder must be specialized by the driver first.'); diff --git a/src/Encoders/AvifEncoder.php b/src/Encoders/AvifEncoder.php index 89c1a8b4..7799950d 100644 --- a/src/Encoders/AvifEncoder.php +++ b/src/Encoders/AvifEncoder.php @@ -8,6 +8,12 @@ class AvifEncoder extends SpecializableEncoder { + /** + * Create new encoder object + * + * @param int $quality + * @return void + */ public function __construct(public int $quality = self::DEFAULT_QUALITY) { } diff --git a/src/Encoders/GifEncoder.php b/src/Encoders/GifEncoder.php index 2f5d0744..65f0224f 100644 --- a/src/Encoders/GifEncoder.php +++ b/src/Encoders/GifEncoder.php @@ -8,6 +8,12 @@ class GifEncoder extends SpecializableEncoder { + /** + * Create new encoder object + * + * @param bool $interlaced + * @return void + */ public function __construct(public bool $interlaced = false) { } diff --git a/src/Encoders/HeicEncoder.php b/src/Encoders/HeicEncoder.php index 8c4272de..2d129a35 100644 --- a/src/Encoders/HeicEncoder.php +++ b/src/Encoders/HeicEncoder.php @@ -8,6 +8,12 @@ class HeicEncoder extends SpecializableEncoder { + /** + * Create new encoder object + * + * @param int $quality + * @return void + */ public function __construct(public int $quality = self::DEFAULT_QUALITY) { } diff --git a/src/Encoders/Jpeg2000Encoder.php b/src/Encoders/Jpeg2000Encoder.php index 67c0ff90..dea11ef2 100644 --- a/src/Encoders/Jpeg2000Encoder.php +++ b/src/Encoders/Jpeg2000Encoder.php @@ -8,6 +8,12 @@ class Jpeg2000Encoder extends SpecializableEncoder { + /** + * Create new encoder object + * + * @param int $quality + * @return void + */ public function __construct(public int $quality = self::DEFAULT_QUALITY) { } diff --git a/src/Encoders/JpegEncoder.php b/src/Encoders/JpegEncoder.php index 5753c249..eaf520e1 100644 --- a/src/Encoders/JpegEncoder.php +++ b/src/Encoders/JpegEncoder.php @@ -8,6 +8,13 @@ class JpegEncoder extends SpecializableEncoder { + /** + * Create new encoder object + * + * @param int $quality + * @param bool $progressive + * @return void + */ public function __construct( public int $quality = self::DEFAULT_QUALITY, public bool $progressive = false diff --git a/src/Encoders/PngEncoder.php b/src/Encoders/PngEncoder.php index 7b2df853..b3376e0d 100644 --- a/src/Encoders/PngEncoder.php +++ b/src/Encoders/PngEncoder.php @@ -8,6 +8,13 @@ class PngEncoder extends SpecializableEncoder { + /** + * Create new encoder object + * + * @param bool $interlaced + * @param bool $indexed + * @return void + */ public function __construct(public bool $interlaced = false, public bool $indexed = false) { } diff --git a/src/Encoders/TiffEncoder.php b/src/Encoders/TiffEncoder.php index 29621892..203baf8c 100644 --- a/src/Encoders/TiffEncoder.php +++ b/src/Encoders/TiffEncoder.php @@ -8,6 +8,12 @@ class TiffEncoder extends SpecializableEncoder { + /** + * Create new encoder object + * + * @param int $quality + * @return void + */ public function __construct(public int $quality = self::DEFAULT_QUALITY) { } diff --git a/src/Encoders/WebpEncoder.php b/src/Encoders/WebpEncoder.php index 535d6b79..5530b6e6 100644 --- a/src/Encoders/WebpEncoder.php +++ b/src/Encoders/WebpEncoder.php @@ -8,6 +8,12 @@ class WebpEncoder extends SpecializableEncoder { + /** + * Create new encoder object + * + * @param int $quality + * @return void + */ public function __construct(public int $quality = self::DEFAULT_QUALITY) { } diff --git a/src/Interfaces/ProfileInterface.php b/src/Interfaces/ProfileInterface.php index 925aae36..8453fda7 100644 --- a/src/Interfaces/ProfileInterface.php +++ b/src/Interfaces/ProfileInterface.php @@ -6,5 +6,10 @@ interface ProfileInterface { + /** + * Cast color profile object to string + * + * @return string + */ public function __toString(): string; } diff --git a/src/Modifiers/BlendTransparencyModifier.php b/src/Modifiers/BlendTransparencyModifier.php index 6e330c44..0e8958fb 100644 --- a/src/Modifiers/BlendTransparencyModifier.php +++ b/src/Modifiers/BlendTransparencyModifier.php @@ -8,6 +8,12 @@ class BlendTransparencyModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param mixed $color + * @return void + */ public function __construct(public mixed $color = null) { } diff --git a/src/Modifiers/ColorizeModifier.php b/src/Modifiers/ColorizeModifier.php index 2fe28721..b3330baf 100644 --- a/src/Modifiers/ColorizeModifier.php +++ b/src/Modifiers/ColorizeModifier.php @@ -8,6 +8,14 @@ class ColorizeModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param int $red + * @param int $green + * @param int $blue + * @return void + */ public function __construct( public int $red = 0, public int $green = 0, diff --git a/src/Modifiers/ContrastModifier.php b/src/Modifiers/ContrastModifier.php index e61f5832..01f726ab 100644 --- a/src/Modifiers/ContrastModifier.php +++ b/src/Modifiers/ContrastModifier.php @@ -8,6 +8,12 @@ class ContrastModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param int $level + * @return void + */ public function __construct(public int $level) { } diff --git a/src/Modifiers/CoverModifier.php b/src/Modifiers/CoverModifier.php index 61e5acc5..a49e26a2 100644 --- a/src/Modifiers/CoverModifier.php +++ b/src/Modifiers/CoverModifier.php @@ -12,6 +12,14 @@ class CoverModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param int $width + * @param int $height + * @param string $position + * @return void + */ public function __construct( public int $width, public int $height, diff --git a/src/Modifiers/CropModifier.php b/src/Modifiers/CropModifier.php index ffc6b499..c4c9b157 100644 --- a/src/Modifiers/CropModifier.php +++ b/src/Modifiers/CropModifier.php @@ -12,6 +12,17 @@ class CropModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param int $width + * @param int $height + * @param int $offset_x + * @param int $offset_y + * @param mixed $background + * @param string $position + * @return void + */ public function __construct( public int $width, public int $height, diff --git a/src/Modifiers/DrawBezierModifier.php b/src/Modifiers/DrawBezierModifier.php index 5bac23ed..f4b1555c 100644 --- a/src/Modifiers/DrawBezierModifier.php +++ b/src/Modifiers/DrawBezierModifier.php @@ -9,10 +9,21 @@ class DrawBezierModifier extends AbstractDrawModifier { + /** + * Create new modifier object + * + * @param Bezier $drawable + * @return void + */ public function __construct(public Bezier $drawable) { } + /** + * Return object to be drawn + * + * @return DrawableInterface + */ public function drawable(): DrawableInterface { return $this->drawable; diff --git a/src/Modifiers/DrawLineModifier.php b/src/Modifiers/DrawLineModifier.php index 4997124b..1e881bad 100644 --- a/src/Modifiers/DrawLineModifier.php +++ b/src/Modifiers/DrawLineModifier.php @@ -9,10 +9,21 @@ class DrawLineModifier extends AbstractDrawModifier { + /** + * Create new modifier object + * + * @param Line $drawable + * @return void + */ public function __construct(public Line $drawable) { } + /** + * Return object to be drawn + * + * @return DrawableInterface + */ public function drawable(): DrawableInterface { return $this->drawable; diff --git a/src/Modifiers/DrawPixelModifier.php b/src/Modifiers/DrawPixelModifier.php index 6e4d732a..43bf0e79 100644 --- a/src/Modifiers/DrawPixelModifier.php +++ b/src/Modifiers/DrawPixelModifier.php @@ -9,6 +9,13 @@ class DrawPixelModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param PointInterface $position + * @param mixed $color + * @return void + */ public function __construct( public PointInterface $position, public mixed $color diff --git a/src/Modifiers/DrawRectangleModifier.php b/src/Modifiers/DrawRectangleModifier.php index 03d521c2..2f0e689d 100644 --- a/src/Modifiers/DrawRectangleModifier.php +++ b/src/Modifiers/DrawRectangleModifier.php @@ -9,10 +9,21 @@ class DrawRectangleModifier extends AbstractDrawModifier { + /** + * + * Create new modifier object + * @param Rectangle $drawable + * @return void + */ public function __construct(public Rectangle $drawable) { } + /** + * Return object to be drawn + * + * @return DrawableInterface + */ public function drawable(): DrawableInterface { return $this->drawable; diff --git a/src/Modifiers/PlaceModifier.php b/src/Modifiers/PlaceModifier.php index 836066fa..601e7015 100644 --- a/src/Modifiers/PlaceModifier.php +++ b/src/Modifiers/PlaceModifier.php @@ -11,6 +11,16 @@ class PlaceModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param mixed $element + * @param string $position + * @param int $offset_x + * @param int $offset_y + * @param int $opacity + * @return void + */ public function __construct( public mixed $element, public string $position = 'top-left', diff --git a/src/Modifiers/QuantizeColorsModifier.php b/src/Modifiers/QuantizeColorsModifier.php index 7845582a..226dd646 100644 --- a/src/Modifiers/QuantizeColorsModifier.php +++ b/src/Modifiers/QuantizeColorsModifier.php @@ -8,6 +8,13 @@ class QuantizeColorsModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param int $limit + * @param mixed $background + * @return void + */ public function __construct( public int $limit, public mixed $background = 'ffffff' diff --git a/src/Modifiers/ResizeCanvasModifier.php b/src/Modifiers/ResizeCanvasModifier.php index 8fafbf92..67f041c9 100644 --- a/src/Modifiers/ResizeCanvasModifier.php +++ b/src/Modifiers/ResizeCanvasModifier.php @@ -12,6 +12,15 @@ class ResizeCanvasModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param null|int $width + * @param null|int $height + * @param mixed $background + * @param string $position + * @return void + */ public function __construct( public ?int $width = null, public ?int $height = null, diff --git a/src/Modifiers/ResizeModifier.php b/src/Modifiers/ResizeModifier.php index 51d3783c..d6ad6141 100644 --- a/src/Modifiers/ResizeModifier.php +++ b/src/Modifiers/ResizeModifier.php @@ -8,6 +8,13 @@ class ResizeModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param null|int $width + * @param null|int $height + * @return void + */ public function __construct(public ?int $width = null, public ?int $height = null) { } diff --git a/src/Modifiers/ResolutionModifier.php b/src/Modifiers/ResolutionModifier.php index 49e5efd5..0eb4cc16 100644 --- a/src/Modifiers/ResolutionModifier.php +++ b/src/Modifiers/ResolutionModifier.php @@ -8,6 +8,13 @@ class ResolutionModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param float $x + * @param float $y + * @return void + */ public function __construct(public float $x, public float $y) { } diff --git a/src/Modifiers/TextModifier.php b/src/Modifiers/TextModifier.php index 91a1c6b4..2c0d446b 100644 --- a/src/Modifiers/TextModifier.php +++ b/src/Modifiers/TextModifier.php @@ -14,6 +14,14 @@ class TextModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param string $text + * @param PointInterface $position + * @param FontInterface $font + * @return void + */ public function __construct( public string $text, public PointInterface $position, diff --git a/src/Modifiers/TrimModifier.php b/src/Modifiers/TrimModifier.php index 89fa3992..18e55310 100644 --- a/src/Modifiers/TrimModifier.php +++ b/src/Modifiers/TrimModifier.php @@ -8,6 +8,12 @@ class TrimModifier extends SpecializableModifier { + /** + * Create new modifier object + * + * @param int $tolerance + * @return void + */ public function __construct(public int $tolerance = 0) { } diff --git a/src/Typography/TextBlock.php b/src/Typography/TextBlock.php index d7f648dd..011b34e7 100644 --- a/src/Typography/TextBlock.php +++ b/src/Typography/TextBlock.php @@ -8,6 +8,12 @@ class TextBlock extends Collection { + /** + * Create new text block object + * + * @param string $text + * @return void + */ public function __construct(string $text) { foreach (explode("\n", $text) as $line) {