From 097bfed504f483ef022c884d648a2da33348ba4c Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Thu, 21 Dec 2023 16:23:40 +0100 Subject: [PATCH] Implement Image::encodeByPath() --- src/Encoders/FileExtensionEncoder.php | 13 ++++++++++- src/Encoders/FilePathEncoder.php | 33 +++++++++++++++++++++++++++ src/Image.php | 25 ++++++++++++++++++++ src/Interfaces/ImageInterface.php | 19 +++++++++++++++ src/Origin.php | 10 ++++++++ tests/Drivers/Gd/ImageTest.php | 21 +++++++++++++++++ tests/Drivers/Imagick/ImageTest.php | 21 +++++++++++++++++ 7 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/Encoders/FilePathEncoder.php diff --git a/src/Encoders/FileExtensionEncoder.php b/src/Encoders/FileExtensionEncoder.php index ba318f70..e22e34c6 100644 --- a/src/Encoders/FileExtensionEncoder.php +++ b/src/Encoders/FileExtensionEncoder.php @@ -33,8 +33,19 @@ public function encode(ImageInterface $image): EncodedImageInterface ); } - protected function encoderByFileExtension(string $extension): EncoderInterface + /** + * Create matching encoder for given file extension + * + * @param string $extension + * @return EncoderInterface + * @throws EncoderException + */ + protected function encoderByFileExtension(?string $extension): EncoderInterface { + if (empty($extension)) { + throw new EncoderException('No encoder found for empty file extension.'); + } + return match ($extension) { 'webp' => new WebpEncoder(), 'avif' => new AvifEncoder(), diff --git a/src/Encoders/FilePathEncoder.php b/src/Encoders/FilePathEncoder.php new file mode 100644 index 00000000..f0f1dc62 --- /dev/null +++ b/src/Encoders/FilePathEncoder.php @@ -0,0 +1,33 @@ +encode( + $this->encoderByFileExtension( + is_null($this->path) ? $image->origin()->fileExtension() : pathinfo($this->path, PATHINFO_EXTENSION) + ) + ); + } +} diff --git a/src/Image.php b/src/Image.php index 17582130..c7f09f77 100644 --- a/src/Image.php +++ b/src/Image.php @@ -15,6 +15,7 @@ use Intervention\Image\Encoders\AvifEncoder; use Intervention\Image\Encoders\BmpEncoder; use Intervention\Image\Encoders\FileExtensionEncoder; +use Intervention\Image\Encoders\FilePathEncoder; use Intervention\Image\Encoders\GifEncoder; use Intervention\Image\Encoders\JpegEncoder; use Intervention\Image\Encoders\MediaTypeEncoder; @@ -250,6 +251,20 @@ public function encode(EncoderInterface $encoder = new AutoEncoder()): EncodedIm return $this->driver->resolve($encoder)->encode($this); } + /** + * {@inheritdoc} + * + * @see ImageInterface::save() + */ + public function save(?string $path = null): ImageInterface + { + $path = is_null($path) ? $this->origin()->filePath() : $path; + + $this->encodeByPath($path)->save($path); + + return $this; + } + /** * {@inheritdoc} * @@ -766,6 +781,16 @@ public function encodeByExtension(?string $extension = null): EncodedImageInterf return $this->encode(new FileExtensionEncoder($extension)); } + /** + * {@inheritdoc} + * + * @see ImageInterface::encodeByPath() + */ + public function encodeByPath(?string $path = null): EncodedImageInterface + { + return $this->encode(new FilePathEncoder($path)); + } + /** * {@inheritdoc} * diff --git a/src/Interfaces/ImageInterface.php b/src/Interfaces/ImageInterface.php index 285f760e..bd5affda 100644 --- a/src/Interfaces/ImageInterface.php +++ b/src/Interfaces/ImageInterface.php @@ -67,6 +67,15 @@ public function size(): SizeInterface; */ public function encode(EncoderInterface $encoder): EncodedImage; + /** + * Save the image to the specified path in the file system. If no path is + * given, the image will be saved at its original location. + * + * @param null|string $path + * @return ImageInterface + */ + public function save(?string $path = null): ImageInterface; + /** * Apply given modifier to current image * @@ -576,6 +585,16 @@ public function encodeByMediaType(?string $type = null): EncodedImageInterface; */ public function encodeByExtension(?string $extension = null): EncodedImageInterface; + /** + * Encode the image into the format represented by the given extension of + * the given file path extension is given the image will be encoded to + * the format of the originally read image. + * + * @param null|string $path + * @return EncodedImageInterface + */ + public function encodeByPath(?string $path = null): EncodedImageInterface; + /** * Encode image to JPEG format * diff --git a/src/Origin.php b/src/Origin.php index 1a001f39..ed15a283 100644 --- a/src/Origin.php +++ b/src/Origin.php @@ -35,6 +35,16 @@ public function mimetype(): string return $this->mediaType(); } + /** + * Return file path of origin + * + * @return null|string + */ + public function filePath(): ?string + { + return $this->filePath; + } + /** * Set file path for origin * diff --git a/tests/Drivers/Gd/ImageTest.php b/tests/Drivers/Gd/ImageTest.php index f5d1a093..3f319472 100644 --- a/tests/Drivers/Gd/ImageTest.php +++ b/tests/Drivers/Gd/ImageTest.php @@ -144,6 +144,27 @@ public function testEncodeByExtension(): void $this->assertMediaType('image/png', (string) $result); } + public function testEncodeByPath(): void + { + $result = $this->readTestImage('blue.gif')->encodeByPath(); + $this->assertInstanceOf(EncodedImage::class, $result); + $this->assertMediaType('image/gif', (string) $result); + + $result = $this->readTestImage('blue.gif')->encodeByPath('foo/bar.png'); + $this->assertInstanceOf(EncodedImage::class, $result); + $this->assertMediaType('image/png', (string) $result); + } + + public function testSaveAsFormat(): void + { + $path = __DIR__ . '/tmp.png'; + $result = $this->readTestImage('blue.gif')->save($path); + $this->assertInstanceOf(Image::class, $result); + $this->assertFileExists($path); + $this->assertMediaType('image/png', file_get_contents($path)); + unlink($path); + } + public function testWidthHeightSize(): void { $this->assertEquals(3, $this->image->width()); diff --git a/tests/Drivers/Imagick/ImageTest.php b/tests/Drivers/Imagick/ImageTest.php index dc9116ec..69257b07 100644 --- a/tests/Drivers/Imagick/ImageTest.php +++ b/tests/Drivers/Imagick/ImageTest.php @@ -143,6 +143,27 @@ public function testEncodeByExtension(): void $this->assertMediaType('image/png', (string) $result); } + public function testEncodeByPath(): void + { + $result = $this->readTestImage('blue.gif')->encodeByPath(); + $this->assertInstanceOf(EncodedImage::class, $result); + $this->assertMediaType('image/gif', (string) $result); + + $result = $this->readTestImage('blue.gif')->encodeByPath('foo/bar.png'); + $this->assertInstanceOf(EncodedImage::class, $result); + $this->assertMediaType('image/png', (string) $result); + } + + public function testSaveAsFormat(): void + { + $path = __DIR__ . '/tmp.png'; + $result = $this->readTestImage('blue.gif')->save($path); + $this->assertInstanceOf(Image::class, $result); + $this->assertFileExists($path); + $this->assertMediaType('image/png', file_get_contents($path)); + unlink($path); + } + public function testWidthHeightSize(): void { $this->assertEquals(20, $this->image->width());