diff --git a/system/Images/Handlers/BaseHandler.php b/system/Images/Handlers/BaseHandler.php index 5ec903b1a5f2..4f595383eb0f 100644 --- a/system/Images/Handlers/BaseHandler.php +++ b/system/Images/Handlers/BaseHandler.php @@ -181,26 +181,7 @@ public function withFile(string $path) /** * Make the image resource object if needed */ - protected function ensureResource() - { - if ($this->resource === null) - { - $path = $this->image()->getPathname(); - // if valid image type, make corresponding image resource - switch ($this->image()->imageType) - { - case IMAGETYPE_GIF: - $this->resource = imagecreatefromgif($path); - break; - case IMAGETYPE_JPEG: - $this->resource = imagecreatefromjpeg($path); - break; - case IMAGETYPE_PNG: - $this->resource = imagecreatefrompng($path); - break; - } - } - } + protected abstract function ensureResource(); //-------------------------------------------------------------------- @@ -268,6 +249,21 @@ public function getResource() //-------------------------------------------------------------------- + /** + * Load the temporary image used during the image processing. + * Some functions e.g. save() will only copy and not compress + * your image otherwise. + * + * @return $this + */ + public function withResource() + { + $this->ensureResource(); + return $this; + } + + //-------------------------------------------------------------------- + /** * Resize the image * diff --git a/system/Images/Handlers/GDHandler.php b/system/Images/Handlers/GDHandler.php index d57034c90963..28e08a8e4fbf 100644 --- a/system/Images/Handlers/GDHandler.php +++ b/system/Images/Handlers/GDHandler.php @@ -320,6 +320,16 @@ public function save(string $target = null, int $quality = 90): bool { $target = empty($target) ? $this->image()->getPathname() : $target; + // If no new resource has been created, then we're + // simply copy the existing one. + if (empty($this->resource)) + { + $name = basename($target); + $path = pathinfo($target, PATHINFO_DIRNAME); + + return $this->image()->copy($path, $name); + } + switch ($this->image()->imageType) { case IMAGETYPE_GIF: @@ -426,6 +436,32 @@ protected function createImage(string $path = '', string $imageType = '') //-------------------------------------------------------------------- + /** + * Make the image resource object if needed + */ + protected function ensureResource() + { + if ($this->resource === null) + { + $path = $this->image()->getPathname(); + // if valid image type, make corresponding image resource + switch ($this->image()->imageType) + { + case IMAGETYPE_GIF: + $this->resource = imagecreatefromgif($path); + break; + case IMAGETYPE_JPEG: + $this->resource = imagecreatefromjpeg($path); + break; + case IMAGETYPE_PNG: + $this->resource = imagecreatefrompng($path); + break; + } + } + } + + //-------------------------------------------------------------------- + /** * Add text overlay to an image. * diff --git a/system/Images/Handlers/ImageMagickHandler.php b/system/Images/Handlers/ImageMagickHandler.php index cc5f577dc234..5fbd7d986103 100644 --- a/system/Images/Handlers/ImageMagickHandler.php +++ b/system/Images/Handlers/ImageMagickHandler.php @@ -340,6 +340,18 @@ protected function getResourcePath() //-------------------------------------------------------------------- + /** + * Make the image resource object if needed + * + * @throws \Exception + */ + protected function ensureResource() + { + $this->getResourcePath(); + } + + //-------------------------------------------------------------------- + /** * Handler-specific method for overlaying text on an image. * diff --git a/tests/system/Images/GDHandlerTest.php b/tests/system/Images/GDHandlerTest.php index 4105553c56c8..1439f3b84650 100644 --- a/tests/system/Images/GDHandlerTest.php +++ b/tests/system/Images/GDHandlerTest.php @@ -321,7 +321,22 @@ public function testImageCreation() //-------------------------------------------------------------------- - public function testImageSave() + public function testImageCopy() + { + foreach (['gif', 'jpeg', 'png'] as $type) + { + $this->handler->withFile($this->origin . 'ci-logo.' . $type); + $this->handler->save($this->start . 'work/ci-logo.' . $type); + $this->assertTrue($this->root->hasChild('work/ci-logo.' . $type)); + + $this->assertEquals( + file_get_contents($this->origin . 'ci-logo.' . $type), + $this->root->getChild('work/ci-logo.' . $type)->getContent() + ); + } + } + + public function testImageCompressionGetResource() { foreach (['gif', 'jpeg', 'png'] as $type) { @@ -329,6 +344,28 @@ public function testImageSave() $this->handler->getResource(); // make sure resource is loaded $this->handler->save($this->start . 'work/ci-logo.' . $type); $this->assertTrue($this->root->hasChild('work/ci-logo.' . $type)); + + $this->assertNotEquals( + file_get_contents($this->origin . 'ci-logo.' . $type), + $this->root->getChild('work/ci-logo.' . $type)->getContent() + ); + } + } + + public function testImageCompressionWithResource() + { + foreach (['gif', 'jpeg', 'png'] as $type) + { + $this->handler->withFile($this->origin . 'ci-logo.' . $type) + ->withResource() // make sure resource is loaded + ->save($this->start . 'work/ci-logo.' . $type); + + $this->assertTrue($this->root->hasChild('work/ci-logo.' . $type)); + + $this->assertNotEquals( + file_get_contents($this->origin . 'ci-logo.' . $type), + $this->root->getChild('work/ci-logo.' . $type)->getContent() + ); } } diff --git a/user_guide_src/source/libraries/images.rst b/user_guide_src/source/libraries/images.rst index cd105e62a567..b88dcea76f6a 100644 --- a/user_guide_src/source/libraries/images.rst +++ b/user_guide_src/source/libraries/images.rst @@ -98,10 +98,19 @@ only applies to JPEG images and will be ignored otherwise:: $image = \Config\Services::image() ->withFile('/path/to/image/mypic.jpg') + // processing methods ->save('/path/to/image/my_low_quality_pic.jpg', 10); .. note:: Higher quality will result in larger file sizes. See also https://www.php.net/manual/en/function.imagejpeg.php +If you are only interested in changing the image quality without doing any processing. +You will need to include the image resource or you will end up with an exact copy:: + + $image = \Config\Services::image() + ->withFile('/path/to/image/mypic.jpg') + ->withResource() + ->save('/path/to/image/my_low_quality_pic.jpg', 10); + Processing Methods ================== @@ -324,4 +333,3 @@ The possible options that are recognized are as follows: .. note:: The ImageMagick driver does not recognize full server path for fontPath. Instead, simply provide the name of one of the installed system fonts that you wish to use, i.e. Calibri. -