Merge pull request #1553 from gaincoder/v3.0

Add .webp support and fix #1467
This commit is contained in:
Diego Najar 2024-01-28 20:13:39 +01:00 committed by GitHub
commit d586fce4f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 204 additions and 195 deletions

View file

@ -932,7 +932,7 @@ function transformImage($file, $imageDir, $thumbnailDir = false)
// Generate Thumbnail // Generate Thumbnail
if (!empty($thumbnailDir)) { if (!empty($thumbnailDir)) {
if (($fileExtension == 'svg') || ($fileExtension == 'webp')) { if (($fileExtension == 'svg')) {
Filesystem::symlink($image, $thumbnailDir . $nextFilename); Filesystem::symlink($image, $thumbnailDir . $nextFilename);
} else { } else {
$Image = new Image(); $Image = new Image();

View file

@ -2,236 +2,245 @@
class Image { class Image {
private $image; private $image;
private $width; private $width;
private $height; private $height;
private $imageResized; private $imageResized;
public function setImage($fileName, $newWidth, $newHeight, $option="auto") public function setImage($fileName, $newWidth, $newHeight, $option="auto")
{ {
// *** Open up the file // *** Open up the file
$this->image = $this->openImage($fileName); $this->image = $this->openImage($fileName);
// *** Get width and height // *** Get width and height
$this->width = imagesx($this->image); $this->width = imagesx($this->image);
$this->height = imagesy($this->image); $this->height = imagesy($this->image);
$this->resizeImage($newWidth, $newHeight, $option); $this->resizeImage($newWidth, $newHeight, $option);
} }
public function saveImage($savePath, $imageQuality="100", $forceJPG=false, $forcePNG=false) public function saveImage($savePath, $imageQuality="100", $forceJPG=false, $forcePNG=false)
{ {
$extension = strtolower(pathinfo($savePath, PATHINFO_EXTENSION)); $extension = strtolower(pathinfo($savePath, PATHINFO_EXTENSION));
// Remove the extension // Remove the extension
$filename = substr($savePath, 0,strrpos($savePath,'.')); $filename = substr($savePath, 0,strrpos($savePath,'.'));
$path_complete = $filename.'.'.$extension; $path_complete = $filename.'.'.$extension;
if ($forcePNG) { if ($forcePNG) {
$extension = 'png'; $extension = 'png';
} elseif ($forceJPG) { } elseif ($forceJPG) {
$extension = 'jpg'; $extension = 'jpg';
} }
switch ($extension) { switch ($extension) {
case 'jpg': case 'jpg':
case 'jpeg': case 'jpeg':
// Checking for JPG support // Checking for JPG support
if (imagetypes() & IMG_JPG) { if (imagetypes() & IMG_JPG) {
imagejpeg($this->imageResized, $path_complete, $imageQuality); imagejpeg($this->imageResized, $path_complete, $imageQuality);
} }
break; break;
case 'gif': case 'gif':
// Checking for GIF support // Checking for GIF support
if (imagetypes() & IMG_GIF) { if (imagetypes() & IMG_GIF) {
imagegif($this->imageResized, $path_complete); imagegif($this->imageResized, $path_complete);
} }
break; break;
case 'png': case 'png':
// *** Scale quality from 0-100 to 0-9 // *** Scale quality from 0-100 to 0-9
$scaleQuality = round(($imageQuality/100) * 9); $scaleQuality = round(($imageQuality/100) * 9);
// *** Invert quality setting as 0 is best, not 9 // *** Invert quality setting as 0 is best, not 9
$invertScaleQuality = 9 - $scaleQuality; $invertScaleQuality = 9 - $scaleQuality;
// Checking for PNG support // Checking for PNG support
if (imagetypes() & IMG_PNG) { if (imagetypes() & IMG_PNG) {
imagepng($this->imageResized, $path_complete, $invertScaleQuality); imagepng($this->imageResized, $path_complete, $invertScaleQuality);
} }
break; break;
case 'webp':
// Checking for JPG support
if (imagetypes() & IMG_WEBP) {
imagewebp($this->imageResized, $path_complete, $imageQuality);
}
break;
default: default:
// Fail extension detection // Fail extension detection
break; break;
} }
imagedestroy($this->imageResized); imagedestroy($this->imageResized);
} }
private function openImage($file) private function openImage($file)
{ {
// *** Get extension // *** Get extension
$extension = strtolower(strrchr($file, '.')); $extension = strtolower(strrchr($file, '.'));
switch($extension) switch($extension)
{ {
case '.jpg': case '.jpg':
case '.jpeg': case '.jpeg':
$img = imagecreatefromjpeg($file); $img = imagecreatefromjpeg($file);
break; break;
case '.gif': case '.gif':
$img = imagecreatefromgif($file); $img = imagecreatefromgif($file);
break; break;
case '.png': case '.png':
$img = imagecreatefrompng($file); $img = imagecreatefrompng($file);
break; break;
default: case '.webp':
$img = false; $img = imagecreatefromwebp($file);
break; break;
} default:
return $img; $img = false;
} break;
}
return $img;
}
private function resizeImage($newWidth, $newHeight, $option) private function resizeImage($newWidth, $newHeight, $option)
{ {
// *** Get optimal width and height - based on $option // *** Get optimal width and height - based on $option
$optionArray = $this->getDimensions($newWidth, $newHeight, $option); $optionArray = $this->getDimensions($newWidth, $newHeight, $option);
$optimalWidth = $optionArray['optimalWidth']; $optimalWidth = $optionArray['optimalWidth'];
$optimalHeight = $optionArray['optimalHeight']; $optimalHeight = $optionArray['optimalHeight'];
// *** Resample - create image canvas of x, y size // *** Resample - create image canvas of x, y size
$this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight); $this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight);
imagealphablending($this->imageResized, false); imagealphablending($this->imageResized, false);
imagesavealpha($this->imageResized, true); imagesavealpha($this->imageResized, true);
imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height); imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height);
// *** if option is 'crop', then crop too // *** if option is 'crop', then crop too
if ($option == 'crop') { if ($option == 'crop') {
$this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight); $this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight);
} }
} }
private function getDimensions($newWidth, $newHeight, $option) private function getDimensions($newWidth, $newHeight, $option)
{ {
if( ($this->width < $newWidth) and ($this->height < $newHeight) ) if( ($this->width < $newWidth) and ($this->height < $newHeight) )
{ {
return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height); return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
} }
switch ($option) switch ($option)
{ {
case 'exact': case 'exact':
$optimalWidth = $newWidth; $optimalWidth = $newWidth;
$optimalHeight= $newHeight; $optimalHeight= $newHeight;
break; break;
case 'portrait': case 'portrait':
$optimalWidth = $this->getSizeByFixedHeight($newHeight); $optimalWidth = $this->getSizeByFixedHeight($newHeight);
$optimalHeight= $newHeight; $optimalHeight= $newHeight;
break; break;
case 'landscape': case 'landscape':
$optimalWidth = $newWidth; $optimalWidth = $newWidth;
$optimalHeight= $this->getSizeByFixedWidth($newWidth); $optimalHeight= $this->getSizeByFixedWidth($newWidth);
break; break;
case 'auto': case 'auto':
$optionArray = $this->getSizeByAuto($newWidth, $newHeight); $optionArray = $this->getSizeByAuto($newWidth, $newHeight);
$optimalWidth = $optionArray['optimalWidth']; $optimalWidth = $optionArray['optimalWidth'];
$optimalHeight = $optionArray['optimalHeight']; $optimalHeight = $optionArray['optimalHeight'];
break; break;
case 'crop': case 'crop':
$optionArray = $this->getOptimalCrop($newWidth, $newHeight); $optionArray = $this->getOptimalCrop($newWidth, $newHeight);
$optimalWidth = $optionArray['optimalWidth']; $optimalWidth = $optionArray['optimalWidth'];
$optimalHeight = $optionArray['optimalHeight']; $optimalHeight = $optionArray['optimalHeight'];
break; break;
} }
return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight); return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
} }
private function getSizeByFixedHeight($newHeight) private function getSizeByFixedHeight($newHeight)
{ {
$ratio = $this->width / $this->height; $ratio = $this->width / $this->height;
$newWidth = $newHeight * $ratio; $newWidth = $newHeight * $ratio;
return $newWidth; return $newWidth;
} }
private function getSizeByFixedWidth($newWidth) private function getSizeByFixedWidth($newWidth)
{ {
$ratio = $this->height / $this->width; $ratio = $this->height / $this->width;
$newHeight = $newWidth * $ratio; $newHeight = $newWidth * $ratio;
return $newHeight; return $newHeight;
} }
private function getSizeByAuto($newWidth, $newHeight) private function getSizeByAuto($newWidth, $newHeight)
{ {
if ($this->height < $this->width) if ($this->height < $this->width)
// *** Image to be resized is wider (landscape) // *** Image to be resized is wider (landscape)
{ {
$optimalWidth = $newWidth; $optimalWidth = $newWidth;
$optimalHeight= $this->getSizeByFixedWidth($newWidth); $optimalHeight= $this->getSizeByFixedWidth($newWidth);
} }
elseif ($this->height > $this->width) elseif ($this->height > $this->width)
// *** Image to be resized is taller (portrait) // *** Image to be resized is taller (portrait)
{ {
$optimalWidth = $this->getSizeByFixedHeight($newHeight); $optimalWidth = $this->getSizeByFixedHeight($newHeight);
$optimalHeight= $newHeight; $optimalHeight= $newHeight;
} }
else else
// *** Image to be resizerd is a square // *** Image to be resizerd is a square
{ {
if ($newHeight < $newWidth) { if ($newHeight < $newWidth) {
$optimalWidth = $newWidth; $optimalWidth = $newWidth;
$optimalHeight= $this->getSizeByFixedWidth($newWidth); $optimalHeight= $this->getSizeByFixedWidth($newWidth);
} else if ($newHeight > $newWidth) { } else if ($newHeight > $newWidth) {
$optimalWidth = $this->getSizeByFixedHeight($newHeight); $optimalWidth = $this->getSizeByFixedHeight($newHeight);
$optimalHeight= $newHeight; $optimalHeight= $newHeight;
} else { } else {
// *** Sqaure being resized to a square // *** Sqaure being resized to a square
$optimalWidth = $newWidth; $optimalWidth = $newWidth;
$optimalHeight= $newHeight; $optimalHeight= $newHeight;
} }
} }
return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight); return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
} }
private function getOptimalCrop($newWidth, $newHeight) private function getOptimalCrop($newWidth, $newHeight)
{ {
$heightRatio = $this->height / $newHeight; $heightRatio = $this->height / $newHeight;
$widthRatio = $this->width / $newWidth; $widthRatio = $this->width / $newWidth;
if ($heightRatio < $widthRatio) { if ($heightRatio < $widthRatio) {
$optimalRatio = $heightRatio; $optimalRatio = $heightRatio;
} else { } else {
$optimalRatio = $widthRatio; $optimalRatio = $widthRatio;
} }
$optimalHeight = $this->height / $optimalRatio; $optimalHeight = $this->height / $optimalRatio;
$optimalWidth = $this->width / $optimalRatio; $optimalWidth = $this->width / $optimalRatio;
return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight); return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
} }
private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight) private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight)
{ {
// *** Find center - this will be used for the crop // *** Find center - this will be used for the crop
$cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 ); $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
$cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 ); $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
$crop = $this->imageResized; $crop = $this->imageResized;
//imagedestroy($this->imageResized); //imagedestroy($this->imageResized);
// *** Now crop from center to exact requested size // *** Now crop from center to exact requested size
$this->imageResized = imagecreatetruecolor($newWidth , $newHeight); $this->imageResized = imagecreatetruecolor($newWidth , $newHeight);
imagealphablending($this->imageResized, false); imagealphablending($this->imageResized, false);
imagesavealpha($this->imageResized, true); imagesavealpha($this->imageResized, true);
imagecopyresampled($this->imageResized, $crop , 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight); imagecopyresampled($this->imageResized, $crop , 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight);
} }
} }