Files
grzanieplus.pl/plugins/sfThumbnailPlugin/lib/sfGDAdapter.class.php
2025-03-12 17:06:23 +01:00

397 lines
10 KiB
PHP

<?php
/*
* This file is part of the symfony package.
* (c) 2004-2007 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* sfGDAdapter provides a mechanism for creating thumbnail images.
* @see http://www.php.net/gd
*
* @package sfThumbnailPlugin
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author Benjamin Meynell <bmeynell@colorado.edu>
*/
class sfGDAdapter
{
protected
$sourceWidth,
$sourceHeight,
$sourceMime,
$maxWidth,
$maxHeight,
$scale,
$inflate,
$quality,
$source,
$transparent,
$options,
$thumb;
/**
* List of accepted image types based on MIME
* descriptions that this adapter supports
*/
protected $imgTypes = array(
'image/jpeg',
'image/pjpeg',
'image/png',
'image/gif',
'image/webp',
);
/**
* Stores function names for each image type
*/
protected $imgLoaders = array(
'image/jpeg' => 'imagecreatefromjpeg',
'image/pjpeg' => 'imagecreatefromjpeg',
'image/png' => 'imagecreatefrompng',
'image/gif' => 'imagecreatefromgif',
'image/webp' => 'imagecreatefromwebp',
);
/**
* Stores function names for each image type
*/
protected $imgCreators = array(
'image/jpeg' => 'imagejpeg',
'image/pjpeg' => 'imagejpeg',
'image/png' => 'imagepng',
'image/gif' => 'imagegif',
'image/webp' => 'imagewebp',
);
protected static $imageTypeSupported = [];
public static function hasImageTypeSupport($imageType)
{
if (!isset(self::$imageTypeSupported[$imageType]))
{
if (!extension_loaded('gd'))
{
self::$imageTypeSupported[$imageType] = false;
return false;
}
$info = gd_info();
if ('WEBP' == $imageType)
{
$imageType = 'WebP';
}
self::$imageTypeSupported[$imageType] = isset($info[$imageType . ' Support']) && $info[$imageType . ' Support'] ||
isset($info[$imageType . ' Read Support']) && $info[$imageType . ' Read Support'] &&
isset($info[$imageType . ' Create Support']) && $info[$imageType . ' Create Support'];
}
return self::$imageTypeSupported[$imageType];
}
public function __construct($maxWidth, $maxHeight, $scale, $inflate, $quality, $options)
{
if (!extension_loaded('gd'))
{
throw new Exception('GD not enabled. Check your php.ini file.');
}
$this->maxWidth = $maxWidth;
$this->maxHeight = $maxHeight;
$this->scale = $scale;
$this->inflate = $inflate;
$this->quality = $quality;
$this->options = $options;
}
public function loadFile($thumbnail, $image, $auto_crop = false)
{
$this->transparent = false;
$imgData = @GetImageSize($image);
if (!$imgData)
{
throw new Exception(sprintf('Could not load image %s', $image));
}
if (in_array($imgData['mime'], $this->imgTypes))
{
$loader = $this->imgLoaders[$imgData['mime']];
if (!function_exists($loader))
{
throw new Exception(sprintf('Function %s not available. Please enable the GD extension.', $loader));
}
$this->source = $loader($image);
$this->sourceWidth = $imgData[0];
$this->sourceHeight = $imgData[1];
$this->sourceMime = $imgData['mime'];
$thumbnail->initThumb($this->sourceWidth, $this->sourceHeight, $this->maxWidth, $this->maxHeight, $this->scale, $this->inflate, $auto_crop);
$this->thumb = imagecreatetruecolor($thumbnail->getThumbWidth(), $thumbnail->getThumbHeight());
if ($imgData[0] == $this->maxWidth && $imgData[1] == $this->maxHeight)
{
$this->thumb = $this->source;
}
else
{
$mime_type = $this->getSourceMime();
if ($mime_type == 'image/png' || $mime_type == 'image/gif')
{
$this->preserveTransparency($this->thumb, $this->source);
}
if ($mime_type == 'image/png')
{
$this->preserveAlpha($this->thumb);
}
if ($auto_crop && is_array($auto_crop))
{
$w = $auto_crop[2] - $auto_crop[0];
$h = $auto_crop[3] - $auto_crop[1];
imagecopyresampled($this->thumb, $this->source, 0, 0, $auto_crop[0], $auto_crop[1], $thumbnail->getThumbWidth(), $thumbnail->getThumbHeight(), $w, $h);
$this->sharpenImage($this->thumb);
}
else
{
imagecopyresampled($this->thumb, $this->source, 0, 0, 0, 0, $thumbnail->getThumbWidth(), $thumbnail->getThumbHeight(), $imgData[0], $imgData[1]);
if ($auto_crop)
{
$this->freeSource();
$this->thumb = $this->cropImage($this->thumb);
$thumbnail->setThumbWidth(imagesx($this->thumb));
$thumbnail->setThumbHeight(imagesy($this->thumb));
}
$this->sharpenImage($this->thumb);
}
}
return true;
}
else
{
throw new Exception(sprintf('Image MIME type %s not supported', $imgData['mime']));
}
}
protected function sharpenImage($image, $strength = 0.2)
{
$mime_type = $this->getSourceMime();
if (function_exists('imageconvolution') && $mime_type != 'image/png' && $mime_type != 'image/gif') {
// black pixel bug fix
$pixel_fix = imagecolorat($image, 0, 0);
$matrix = array(
array(0, -$strength, 0),
array(-$strength, 8*$strength+1, -$strength),
array(0, -$strength, 0),
);
$divisor = array_sum(array_map('array_sum', $matrix));
imageconvolution($image, $matrix, $divisor, 0);
// black pixel bug fix
imagesetpixel($image, 0, 0, $pixel_fix);
}
}
protected function cropImage($source)
{
$sw = imagesx($source);
$sh = imagesy($source);
$sx = 0;
$sy = 0;
$dw = $sw;
$dh = $sh;
if ($sw > $this->maxWidth)
{
$sx = round(($sw - $this->maxWidth) / 2);
$dw = $sw - $sx * 2;
}
elseif ($sh > $this->maxHeight)
{
$sy = round(($sh - $this->maxHeight) / 2);
$dh = $sh - $sy * 2;
}
$croped = imagecreatetruecolor($dw, $dh);
$mime_type = $this->getSourceMime();
if ($mime_type == 'image/png' || $mime_type == 'image/gif')
{
$this->preserveTransparency($croped, $source);
}
if ($mime_type == 'image/png')
{
$this->preserveAlpha($croped);
}
imagecopyresampled($croped, $source, 0, 0, $sx, $sy, $dw, $dh, $dw, $dh);
imagedestroy($source);
return $croped;
}
public function loadData($thumbnail, $image, $mime)
{
if (in_array($mime, $this->imgTypes))
{
$this->source = imagecreatefromstring($image);
$this->sourceWidth = imagesx($this->source);
$this->sourceHeight = imagesy($this->source);
$this->sourceMime = $mime;
$thumbnail->initThumb($this->sourceWidth, $this->sourceHeight, $this->maxWidth, $this->maxHeight, $this->scale, $this->inflate);
$this->thumb = imagecreatetruecolor($thumbnail->getThumbWidth(), $thumbnail->getThumbHeight());
if ($this->sourceWidth == $this->maxWidth && $this->sourceHeight == $this->maxHeight)
{
$this->thumb = $this->source;
}
else
{
imagecopyresampled($this->thumb, $this->source, 0, 0, 0, 0, $thumbnail->getThumbWidth(), $thumbnail->getThumbHeight(), $this->sourceWidth, $this->sourceHeight);
}
return true;
}
else
{
throw new Exception(sprintf('Image MIME type %s not supported', $mime));
}
}
protected function preserveTransparency($thumb, $source)
{
$trans_index = imagecolortransparent($source);
if ($trans_index >= 0 && $trans_index < imagecolorstotal($source))
{
$this->transparent = true;
$trans_color = imagecolorsforindex($source, $trans_index);
$trans_index = imagecolorallocate($thumb, $trans_color['red'], $trans_color['green'], $trans_color['blue']);
imagefill($thumb, 0, 0, $trans_index);
imagecolortransparent($thumb, $trans_index);
}
else
{
$this->transparent = false;
}
}
protected function preserveAlpha($source)
{
imagealphablending($source, false);
imagesavealpha($source, true);
}
protected function disableAlpha($source)
{
imagealphablending($source, true);
imagesavealpha($source, false);
}
public function save($thumbnail, $thumbDest, $targetMime = null)
{
imageinterlace($this->thumb, true);
if ($targetMime !== null)
{
$creator = $this->imgCreators[$targetMime];
}
else
{
$creator = $this->imgCreators[$thumbnail->getMime()];
}
if (self::hasImageTypeSupport('webp') && isset($this->options['enable_webp_format']) && $this->options['enable_webp_format'])
{
$creator = 'imagewebp';
}
if ($creator == 'imagejpeg')
{
imagejpeg($this->thumb, $thumbDest, $this->quality);
}
else
{
$creator($this->thumb, $thumbDest);
}
}
public function toString($thumbnail, $targetMime = null)
{
if ($targetMime !== null)
{
$creator = $this->imgCreators[$targetMime];
}
else
{
$creator = $this->imgCreators[$thumbnail->getMime()];
}
ob_start();
if ($creator != 'imagegif' && $creator != 'imagepng')
{
$creator($this->thumb, null, $this->quality);
}
else
{
$creator($this->thumb);
}
return ob_get_clean();
}
public function freeSource()
{
if (is_resource($this->source))
{
imagedestroy($this->source);
}
}
public function freeThumb()
{
if (is_resource($this->thumb))
{
imagedestroy($this->thumb);
}
}
public function getSourceMime()
{
return $this->sourceMime;
}
}