Merge pull request #1553 from gaincoder/v3.0
Add .webp support and fix #1467
This commit is contained in:
commit
d586fce4f2
2 changed files with 204 additions and 195 deletions
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue