diff --git a/wire/core/ImageSizer.php b/wire/core/ImageSizer.php index f556281a..9d0104f8 100755 --- a/wire/core/ImageSizer.php +++ b/wire/core/ImageSizer.php @@ -55,6 +55,14 @@ class ImageSizer extends Wire { */ static protected $knownEngines = null; + /** + * Names of engines that failed the supported() checks + * + * @var array + * + */ + protected $failedEngineNames = array(); + /** * Module/class name of engine that must only be used (for cases where you want to force a specific engine) * @@ -84,7 +92,6 @@ class ImageSizer extends Wire { * * @param string $filename Filename to resize. Omit only if instantiating class for a getEngines() call. * @param array $options Initial options to the engine. - * @throws WireException * */ public function __construct($filename = '', $options = array()) { @@ -152,21 +159,50 @@ class ImageSizer extends Wire { } $engine = null; + $bestFallbackEngine = null; // first engine that was supported but failed webp check + $engineNames = $this->getEngines(); + $engineNames[] = $this->defaultEngineName; // find first supported engine, according to knownEngines priority - foreach($this->getEngines() as $engineName) { + foreach($engineNames as $engineName) { + if($this->forceEngineName && $engineName != $this->forceEngineName) continue; - $e = $this->wire('modules')->get($engineName); + + if($engineName === $this->defaultEngineName) { + $engineClass = __NAMESPACE__ . "\\$engineName"; + $e = $this->wire(new $engineClass()); + } else { + $e = $this->wire('modules')->get($engineName); + } + + if(!$e) continue; + + /** @var ImageSizerEngine $e */ $e->prepare($filename, $options, $inspectionResult); - if($e->supported()) { + $supported = $e->supported(); + + if($supported && !empty($options['webpAdd']) && !$e->supported('webp')) { + // engine does not support requested webp extra image + if(!$bestFallbackEngine) $bestFallbackEngine = $e; + + } else if($supported) { + // found supported engine $engine = $e; break; - } + } + + $this->failedEngineNames[$engineName] = $engineName; } - if(!$engine) { - // fallback to default - $engine = $this->newDefaultImageSizerEngine($filename, $options, $inspectionResult); + if(!$engine) { + // no engine found + if($bestFallbackEngine) { + // if there is a next best fallback, use it + $engine = $bestFallbackEngine; + } else { + // otherwise fallback to default + $engine = $this->newDefaultImageSizerEngine($filename, $options, $inspectionResult); + } } return $engine; @@ -294,11 +330,10 @@ class ImageSizer extends Wire { * */ public function setModified($modified) { - if($this->engine) $this->engine->modified = $modified ? true : false; + if($this->engine) $this->engine->setModified($modified ? true : false); return $this; } - // setters (@todo phpdocs) public function setAutoRotation($value = true) { return $this->setOptions(array('autoRotation', $value)); } public function setCropExtra($value) { return $this->setOptions(array('cropExtra', $value)); } public function setCropping($cropping = true) { return $this->setOptions(array('cropping', $cropping)); } @@ -312,7 +347,6 @@ class ImageSizer extends Wire { public function setTimeLimit($value = 30) { return $this->setOptions(array('timeLimit', $value)); } public function setUpscaling($value = true) { return $this->setOptions(array('upscaling', $value)); } public function setUseUSM($value = true) { return $this->setOptions(array('useUSM', $value)); } - public function getWidth() { $image = $this->getEngine()->get('image'); return $image['width']; @@ -321,12 +355,12 @@ class ImageSizer extends Wire { $image = $this->getEngine()->get('image'); return $image['height']; } - - public function getFilename() { return $this->getEngine()->filename; } - public function getExtension() { return $this->getEngine()->extension; } - public function getImageType() { return $this->getEngine()->imageType; } - public function isModified() { return $this->getEngine()->modified; } + public function getFilename() { return $this->getEngine()->getFilename(); } + public function getExtension() { return $this->getEngine()->getExtension(); } + public function getImageType() { return $this->getEngine()->getImageType(); } + public function isModified() { return $this->getEngine()->getModified(); } public function getOptions() { return $this->getEngine()->getOptions(); } + public function getFailedEngineNames() { return $this->failedEngineNames; } /** * Get the current ImageSizerEngine @@ -533,7 +567,7 @@ class ImageSizer extends Wire { } else { return null; } - $sizer = new ImageSizerEngineGD($filename); + $sizer = new ImageSizerEngineGD(); if($wire) $wire->wire($sizer); $result = false !== $sizer->writeBackIPTC($filename) ? true : false; return $result; diff --git a/wire/core/ImageSizerEngine.php b/wire/core/ImageSizerEngine.php index de09c4dc..be7ba089 100755 --- a/wire/core/ImageSizerEngine.php +++ b/wire/core/ImageSizerEngine.php @@ -21,6 +21,7 @@ * @property bool $webpAdd * @property int $webpQuality * @property bool|null $webpResult + * @property bool|null $webpOnly * */ abstract class ImageSizerEngine extends WireData implements Module, ConfigurableModule { @@ -79,6 +80,14 @@ abstract class ImageSizerEngine extends WireData implements Module, Configurable */ protected $webpAdd = false; + /** + * Only create the webp file? + * + * @var bool + * + */ + protected $webpOnly = false; + /** * webp result (null=not known or not applicable) * @@ -931,13 +940,27 @@ abstract class ImageSizerEngine extends WireData implements Module, Configurable /** * Set flag to also create a webp file or not * - * @param bool $value - * + * @param bool $webpAdd + * @param bool|null $webpOnly * @return self * */ - public function setWebpAdd($value) { - $this->webpAdd = (bool) $value; + public function setWebpAdd($webpAdd, $webpOnly = null) { + $this->webpAdd = (bool) $webpAdd; + if(is_bool($webpOnly)) $this->webpOnly = $webpOnly; + return $this; + } + + /** + * Set flag to only create a webp file + * + * @param bool value$ + * @return self + * + */ + public function setWebpOnly($value) { + $this->webpOnly = (bool) $value; + if($this->webpOnly) $this->webpAdd = true; // webpAdd required for webpOnly return $this; } @@ -1207,6 +1230,9 @@ abstract class ImageSizerEngine extends WireData implements Module, Configurable case 'webpAdd': $this->setWebpAdd($value); break; + case 'webpOnly': + $this->webpOnly = (bool) $value; + break; case 'cropping': $this->setCropping($value); break; @@ -1287,6 +1313,7 @@ abstract class ImageSizerEngine extends WireData implements Module, Configurable 'quality' => $this->quality, 'webpQuality' => $this->webpQuality, 'webpAdd' => $this->webpAdd, + 'webpOnly' => $this->webpOnly, 'cropping' => $this->cropping, 'upscaling' => $this->upscaling, 'interlace' => $this->interlace, @@ -1328,6 +1355,7 @@ abstract class ImageSizerEngine extends WireData implements Module, Configurable ); if($key === 'webpResult') return $this->webpResult; + if($key === 'webpOnly') return $this->webpOnly; if(in_array($key, $keys)) return $this->$key; if(in_array($key, $this->optionNames)) return $this->$key; if(isset($this->options[$key])) return $this->options[$key]; @@ -1476,6 +1504,16 @@ abstract class ImageSizerEngine extends WireData implements Module, Configurable return $this; } + /** + * Get whether the image was modified + * + * @return bool + * + */ + public function getModified() { + return $this->modified; + } + /** * Check if cropping is needed, if yes, populate x- and y-position to params $w1 and $h1 * diff --git a/wire/core/ImageSizerEngineGD.php b/wire/core/ImageSizerEngineGD.php index a2c97425..45c89600 100755 --- a/wire/core/ImageSizerEngineGD.php +++ b/wire/core/ImageSizerEngineGD.php @@ -36,14 +36,6 @@ class ImageSizerEngineGD extends ImageSizerEngine { */ protected $gammaLinearized; - /** - * webp-only toggle for future use - * - * @var bool - * - */ - protected $webpOnly = false; - /** * Webp support available? * diff --git a/wire/core/PagefileExtra.php b/wire/core/PagefileExtra.php index b319c992..223a4d59 100644 --- a/wire/core/PagefileExtra.php +++ b/wire/core/PagefileExtra.php @@ -2,7 +2,9 @@ /** * Extra extension for Pagefile or Pageimage objects - * + * + * Properties + * ========== * @property string $url Local URL/path to file * @property string $httpUrl Full HTTP URL with scheme and host * @property string $URL No-cache version of url @@ -14,9 +16,16 @@ * @property string $ext Alias of extension * @property bool $exists Does the file exist? * @property int $filesize Size of file in bytes - * @property Pageimage $pagefile Source Pageimage objerct + * @property Pagefile|Pageimage $pagefile Source Pageimage object * - * @method create() + * The following properties affect the behavior of the URL-related methods + * ======================================================================= + * @property bool $useSrcUrlOnFail Use source Pagefile URL if extra image does not exist and cannot be created? (default=false) + * @property bool $useSrcUrlOnSize Use source Pagefile URL if extra file is larger than source file? (default=false) + * + * Hookable methods + * ================ + * @method bool create() * */ @@ -41,7 +50,7 @@ class PagefileExtra extends WireData { * */ protected $filenamePrevious = ''; - + /** * Construct * @@ -53,6 +62,8 @@ class PagefileExtra extends WireData { $pagefile->wire($this); $this->setPagefile($pagefile); $this->setExtension($extension); + $this->useSrcUrlOnFail = true; + $this->useSrcUrlOnSize = false; return parent::__construct(); } @@ -79,10 +90,12 @@ class PagefileExtra extends WireData { /** * Does the extra file currently exist? * + * @param bool $clear Clear stat cache before checking? (default=false) * @return bool * */ - public function exists() { + public function exists($clear = false) { + if($clear) clearstatcache(); return is_readable($this->filename()); } @@ -93,7 +106,7 @@ class PagefileExtra extends WireData { * */ public function filesize() { - return $this->exists() ? filesize($this->filename()) : 0; + return (int) @filesize($this->filename()); } /** @@ -122,13 +135,26 @@ class PagefileExtra extends WireData { /** * Return the URL to the extra file, creating it if it does not already exist * + * @param bool $fallback Allow falling back to source Pagefile URL when appropriate? * @return string * */ - public function url() { - if(!$this->exists()) $this->create(); - $pathinfo = pathinfo($this->pagefile->url()); - return $pathinfo['dirname'] . '/' . $pathinfo['filename'] . '.' . $this->extension; + public function url($fallback = true) { + if(!$this->exists()) { + $this->create(); + if($fallback && !$this->exists() && $this->useSrcUrlOnFail) { + // return original pagefile URL if the extra cannot be created + return $this->pagefile->url(); + } + } + if($fallback && $this->useSrcUrlOnSize && $this->filesize() > $this->pagefile->filesize()) { + $url = $this->pagefile->url(); + } else { + $pathinfo = pathinfo($this->pagefile->url()); + $url = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . '.' . $this->extension; + } + + return $url; } /** @@ -169,8 +195,12 @@ class PagefileExtra extends WireData { * * Must be implemented by a hook or by descending class * + * @return bool Returns true on success, false on fail + * */ - public function ___create() { } + public function ___create() { + return false; + } /** * Get property @@ -212,7 +242,8 @@ class PagefileExtra extends WireData { $value = $this->pagefile; break; default: - $value = $this->pagefile->get($key); + $value = parent::get($key); + if($value === null) $value = $this->pagefile->get($key); } return $value; } diff --git a/wire/core/Pageimage.php b/wire/core/Pageimage.php index 1cf88ad6..ed33aa63 100644 --- a/wire/core/Pageimage.php +++ b/wire/core/Pageimage.php @@ -645,7 +645,8 @@ class Pageimage extends Pagefile { * */ protected function ___size($width, $height, $options) { - + + $this->error = ''; if($this->ext == 'svg') return $this; if(!is_array($options)) { @@ -678,6 +679,8 @@ class Pageimage extends Pagefile { 'hidpiQuality' => 40, 'webpQuality' => 90, 'webpAdd' => false, + 'webpName' => '', // use this for the webp file basename rather than mirroring from the jpg/png + 'webpOnly' => false, // only keep the webp version (requires webpAdd option) 'suffix' => array(), // can be array of suffixes or string of 1 suffix 'forceNew' => false, // force it to create new image even if already exists 'hidpi' => false, @@ -691,8 +694,6 @@ class Pageimage extends Pagefile { 'allowOriginal' => false, // Return original image if already at requested dimensions? (must be only specified option) ); - $this->error = ''; - /** @var WireFileTools $files */ /** @var Config $config */ $files = $this->wire('files'); @@ -786,11 +787,16 @@ class Pageimage extends Pagefile { $filenameFinal = $this->pagefiles->path() . $basename; $filenameFinalExists = file_exists($filenameFinal); - $filenameFinalWebp = $this->pagefiles->path() . $basenameNoExt . '.webp'; + + if(!empty($options['webpName'])) { + $filenameFinalWebp = $this->pagefiles->path() . basename($options['webpName'], '.webp') . '.webp'; + } else { + $filenameFinalWebp = $this->pagefiles->path() . $basenameNoExt . '.webp'; + } // force new creation if requested webp copy doesn't exist, (regardless if regular variation exists or not) if($options['webpAdd'] && !file_exists($filenameFinalWebp)) $options['forceNew'] = true; - + // create a new resize if it doesn't already exist or forceNew option is set if(!$filenameFinalExists && !file_exists($this->filename())) { // no original file exists to create variation from @@ -801,7 +807,7 @@ class Pageimage extends Pagefile { // filenameUnvalidated is temporary filename used for resize $tempDir = $this->pagefiles->page->filesManager()->getTempPath(); $filenameUnvalidated = $tempDir . $basename; - $filenameUnvalidatedWebp = $tempDir . basename($filenameFinalWebp); + $filenameUnvalidatedWebp = $tempDir . $basenameNoExt . '.webp'; if($filenameFinalExists && $options['forceNew']) $files->unlink($filenameFinal, true); if(file_exists($filenameFinalWebp) && $options['forceNew']) $files->unlink($filenameFinalWebp, true); @@ -822,7 +828,9 @@ class Pageimage extends Pagefile { /* if the current engine installation does not support webp, modify the options param */ if(!empty($options['webpAdd']) && !$engine->supported('webp')) { + // no engines support webp $options['webpAdd'] = false; + $options['webpOnly'] = false; $engine->setOptions($options); } @@ -840,7 +848,12 @@ class Pageimage extends Pagefile { } } - if($sizer->resize($width, $height) && $files->rename($filenameUnvalidated, $filenameFinal)) { + if($sizer->resize($width, $height)) { + if($options['webpAdd'] && $options['webpOnly']) { + if(is_file($filenameUnvalidated)) $files->unlink($filenameUnvalidated); + } else if(!$files->rename($filenameUnvalidated, $filenameFinal)) { + $this->error = "Rename failed: $filenameUnvalidated => $filenameFinal"; + } if($options['webpAdd'] && file_exists($filenameUnvalidatedWebp)) { $files->rename($filenameUnvalidatedWebp, $filenameFinalWebp); } @@ -848,7 +861,7 @@ class Pageimage extends Pagefile { $this->error = "ImageSizer::resize($width, $height) failed for $filenameUnvalidated"; } - if($debug) $this->wire('log')->save('image-sizer', + if($debug && empty($options['webpOnly'])) $this->wire('log')->save('image-sizer', str_replace('ImageSizerEngine', '', $sizer->getEngine()) . ' ' . ($this->error ? "FAILED Resize: " : "Resized: ") . "$originalName => " . basename($filenameFinal) . " " . "({$width}x{$height}) " . Debug::timer($timer) . " secs $originalSize => " . filesize($filenameFinal) . " bytes " . @@ -1896,6 +1909,8 @@ class Pageimage extends Pagefile { $webp = $this->extras('webp'); if(!$webp) { $webp = new PagefileExtra($this, 'webp'); + $webp->useSrcUrlOnFail = true; // use this pagefile URL instead if we fail to create a webp + $webp->useSrcUrlOnSize = true; // use webp URL only if it results in a smaller file $this->extras('webp', $webp); $webp->addHookAfter('create', $this, 'hookWebpCreate'); } @@ -1911,13 +1926,30 @@ class Pageimage extends Pagefile { * */ public function hookWebpCreate(HookEvent $event) { - if(!$this->original) return; + $original = $this->original; /** @var PagefileExtra $webp */ $webp = $event->object; $webp->unlink(); - $options = self::$lastSizeOptions; + if($original) { + // we are in an image resized from an original + $options = self::$lastSizeOptions; + $width = $options['_width']; + $height = $options['_height']; + } else { + // we are the original + // create a file with same name as original but with .webp extension + $original = $this; + $options = array( + 'allowOriginal' => false, + 'webpName' => basename($this->basename(), ".$this->ext"), + 'webpOnly' => true + ); + $width = $this->width; + $height = 0; + } $options['webpAdd'] = true; - $this->original->size($options['_width'], $options['_height'], $options); + $original->size($width, $height, $options); + $event->return = empty($this->error); } /** diff --git a/wire/core/PageimageDebugInfo.php b/wire/core/PageimageDebugInfo.php index 9c6d5324..ee42d02a 100644 --- a/wire/core/PageimageDebugInfo.php +++ b/wire/core/PageimageDebugInfo.php @@ -275,7 +275,7 @@ class PageimageDebugInfo extends WireData { $return = $content; } else { // build output for HTML - $return = "
" . $this->wire('sanitizer')->entities($content) . ""; + $return = "
$content"; } return $return; diff --git a/wire/modules/Image/ImageSizerEngineIMagick/ImageSizerEngineIMagick.module b/wire/modules/Image/ImageSizerEngineIMagick/ImageSizerEngineIMagick.module index f42a52a8..b0275bb0 100755 --- a/wire/modules/Image/ImageSizerEngineIMagick/ImageSizerEngineIMagick.module +++ b/wire/modules/Image/ImageSizerEngineIMagick/ImageSizerEngineIMagick.module @@ -36,13 +36,12 @@ class ImageSizerEngineIMagick extends ImageSizerEngine { protected $imWebp = null; /** - * Webp support available? + * Static cache of formats and whether or not supported, as used by the supportsFormat() method (RJC) * - * @var bool|null + * @var array of ['FORMAT' => true|false] * */ - static protected $webpSupport = null; - + static protected $formatSupport = array(); // @todo the following need phpdoc protected $workspaceColorspace; @@ -116,7 +115,7 @@ class ImageSizerEngineIMagick extends ImageSizerEngine { * */ protected function validSourceImageFormats() { - return array('JPG', 'JPEG', 'PNG24'); + return array('JPG', 'JPEG', 'PNG24', 'PNG8', 'PNG', 'GIF', 'GIF87'); //return array( // 'PNG', 'PNG8', 'PNG24', // 'JPG', 'JPEG', @@ -131,16 +130,33 @@ class ImageSizerEngineIMagick extends ImageSizerEngine { * */ protected function validTargetImageFormats() { - return $this->validSourceImageFormats(); + $formats = $this->validSourceImageFormats(); + if($this->supportsFormat('WEBP')) $formats[] = 'WEBP'; + return $formats; + } + + /** + * Is the given image format supported by this IMagick for source and target? (RJC) + * + * @param string $format String like png, jpg, jpg, png8, png24, png24-trans, png24-alpha, etc. + * @return bool + * + */ + public function supportsFormat($format) { + if(strpos($format, '-')) list($format,) = explode('-', $format); + $format = strtoupper($format); + if(isset(self::$formatSupport[$format])) return self::$formatSupport[$format]; + try { + $im = new \IMagick(); + $formats = $im->queryformats($format); + $supported = count($formats) > 0; + } catch(\Exception $e) { + $supported = false; + } + self::$formatSupport[$format] = $supported; + return $supported; } - /** - * Is IMagick supported? Is the current image(sub)format supported? - * - * @param string $action - * @return bool - * - */ /** * Is IMagick supported? Is the current image(sub)format supported? * @@ -154,40 +170,21 @@ class ImageSizerEngineIMagick extends ImageSizerEngine { if(!class_exists("\\IMagick")) return false; // and if it passes the mandatory requirements, we check particularly aspects here - switch($action) { - - case 'imageformat': - // compare current imagefile infos fetched from ImageInspector - $requested = $this->getImageInfo(false); - switch($requested) { - case 'jpg': - return true; - case 'png24': - case 'png24-trans': - case 'png24-alpha': - return true; - default: - return false; - } - break; - - case 'webp': - if(self::$webpSupport === null) { - $im = new \IMagick(); - $formats = $im->queryformats('WEBP*'); - self::$webpSupport = count($formats) > 0; - } - return self::$webpSupport; - break; - - case 'install': - return true; - - default: - return false; + $supported = false; + if($action === 'imageformat') { + // compare current imagefile infos fetched from ImageInspector + $requested = $this->getImageInfo(false); + $supported = $this->supportsFormat($requested); + } else if($action === 'webp') { + $supported = $this->supportsFormat('WEBP'); + } else if($action === 'install') { + $supported = true; } + + return $supported; } + /** * Process the image resize * @@ -232,16 +229,16 @@ class ImageSizerEngineIMagick extends ImageSizerEngine { $this->imageFormat = strtoupper($this->im->getImageFormat()); // only for JPEGs and 24bit PNGs - if(!in_array($this->imageFormat, array('JPG', 'JPEG', 'PNG24'))) { + if(!in_array($this->imageFormat, $this->validSourceImageFormats())) { $this->release(); return false; } - // check validity against PW - if(!in_array($this->imageFormat, $this->validSourceImageFormats())) { - $this->release(); - throw new WireException(sprintf($this->_("loaded file '%s' is not in the list of valid images"), basename($dstFilename))); - } + // check validity against PW (this does not seem to be reachable due to above code, so commented it out —Ryan) + // if(!in_array($this->imageFormat, $this->validSourceImageFormats())) { + // $this->release(); + // throw new WireException(sprintf($this->_("loaded file '%s' is not in the list of valid images"), basename($dstFilename))); + // } // check and retrieve different image parts and information: ICC, Colorspace, Colordepth, Metadata, etc $this->imageColorspace = $this->im->getImageColorspace(); @@ -385,46 +382,53 @@ class ImageSizerEngineIMagick extends ImageSizerEngine { } $this->im->setImageDepth(($this->imageDepth > 8 ? 8 : $this->imageDepth)); + + // determine whether webp should be created as well (or on its own) + $webpOnly = $this->webpOnly && $this->supported('webp'); + $webpAdd = $webpOnly || ($this->webpAdd && $this->supported('webp')); - // prepare to save file(s) - if($this->webpAdd && $this->supported('webp')) { - $this->imWebp = clone $this->im; // make a copy before compressions take effect - } - - $this->im->setImageFormat($this->imageFormat); - $this->im->setImageType($this->imageType); - if(in_array(strtoupper($this->imageFormat), array('JPG', 'JPEG'))) { - $this->im->setImageCompression(\Imagick::COMPRESSION_JPEG); - $this->im->setImageCompressionQuality($this->quality); - } else if(in_array(strtoupper($this->imageFormat), array('PNG', 'PNG8', 'PNG24'))) { - $this->im->setImageCompression(\Imagick::COMPRESSION_ZIP); - $this->im->setImageCompressionQuality($this->quality); + if($webpOnly) { + // only a webp file will be created + $this->imWebp = $this->im; } else { - $this->im->setImageCompression(\Imagick::COMPRESSION_UNDEFINED); - $this->im->setImageCompressionQuality($this->quality); - } + if($webpAdd) $this->imWebp = clone $this->im; // make a copy before compressions take effect + $this->im->setImageFormat($this->imageFormat); + $this->im->setImageType($this->imageType); + if(in_array(strtoupper($this->imageFormat), array('JPG', 'JPEG'))) { + $this->im->setImageCompression(\Imagick::COMPRESSION_JPEG); + $this->im->setImageCompressionQuality($this->quality); + } else if(in_array(strtoupper($this->imageFormat), array('PNG', 'PNG8', 'PNG24'))) { + $this->im->setImageCompression(\Imagick::COMPRESSION_ZIP); + $this->im->setImageCompressionQuality($this->quality); + } else { + $this->im->setImageCompression(\Imagick::COMPRESSION_UNDEFINED); + $this->im->setImageCompressionQuality($this->quality); + } - // write to file - if(file_exists($dstFilename)) $this->wire('files')->unlink($dstFilename); - @clearstatcache(dirname($dstFilename)); - ##if(!$this->im->writeImage($this->destFilename)) { - // We use this approach for saving so that it behaves the same like core ImageSizer with images that - // have a wrong extension in their filename. When using writeImage() it automatically corrects the - // mimetype to match the fileextension, <- we want to avoid this! - if(!file_put_contents($dstFilename, $this->im)) { - $this->release(); - return false; + // write to file + if(file_exists($dstFilename)) $this->wire('files')->unlink($dstFilename); + @clearstatcache(dirname($dstFilename)); + ##if(!$this->im->writeImage($this->destFilename)) { + // We use this approach for saving so that it behaves the same like core ImageSizer with images that + // have a wrong extension in their filename. When using writeImage() it automatically corrects the + // mimetype to match the fileextension, <- we want to avoid this! + if(!file_put_contents($dstFilename, $this->im)) { + $this->release(); + return false; + } } - + // set modified flag and delete optional webp dependency file $this->modified = true; $return = true; + + // if there is a corresponding webp file present, remove it $pathinfo = pathinfo($srcFilename); $webpFilename = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . '.webp'; if(file_exists($webpFilename)) $this->wire('files')->unlink($webpFilename); - + // optionally create a WebP dependency file - if($this->webpAdd && $this->imWebp) { + if($webpAdd) { // prepare for webp output $this->imWebp->setImageFormat('webp'); $this->imWebp->setImageCompressionQuality($this->webpQuality); @@ -438,6 +442,7 @@ class ImageSizerEngineIMagick extends ImageSizerEngine { // release and return to event-object $this->release(); + return $return; }