params = Yii::app()->params['imagephp'] ?? [];
$this->image = $options['image'] ?? '';
$this->imagePath = realpath(Yii::web()->uploadSaver->uploadsPath . '/..' . $this->image);
$this->width = $options['width'] ?? false;
$this->height = $options['height'] ?? false;
$this->cropRatio = $options['cropRatio'] ?? false;
$this->showWatermark = $options['showWatermark'] ?? false;
$this->croppedImage();
if ($this->showWatermark && isset($this->params['watermarkPath'])) {
$this->watermarkedImage($this->imageCroppedPath);
}
}
protected function croppedImage()
{
$filename = sha1(basename($this->imagePath) . $this->width . $this->height . $this->cropRatio);
$path = $this->getNestedDir($filename);
$this->imageCroppedPath = Yii::web()->uploadSaver->uploadsPath . '/' . $path . '/' . $filename . '.' . $this->getExt();
if (!file_exists($this->imageCroppedPath)) {
$this->cropImage();
}
}
protected function getNestedDir($fileName, $depth = 4)
{
if (!$this->nestedDir) {
$len = strlen($fileName);
$res = [];
for ($i = 0; $i < $len && $i < $depth * 2; $i += 2) {
$res[] = substr($fileName, $i, 2);
@mkdir(Yii::web()->uploadSaver->uploadsPath . '/' . implode('/', $res), 0777);
}
$this->nestedDir = implode('/', $res);
}
return $this->nestedDir;
}
public function getExt()
{
$fileNameArr = explode('.', $this->imagePath);
return array_pop($fileNameArr);
}
protected function cropImage()
{
// Get the size and MIME type of the requested image
$size = getImageSize($this->imagePath);
$width = $size[0];
$height = $size[1];
list($maxWidth, $maxHeight) = $this->calculateMaxes($width, $height);
$offsetX = 0;
$offsetY = 0;
list($width, $height, $offsetX, $offsetY) = $this->calculateCrop($width, $height, $offsetX, $offsetY);
// Setting up the ratios needed for resizing. We will compare these below to determine how to
// resize the image (based on height or based on width)
$xRatio = $maxWidth / $width;
$yRatio = $maxHeight / $height;
// If either a max width or max height are not specified, we default to something
// large so the unspecified dimension isn't a constraint on our resized image.
// If neither are specified but the color is, we aren't going to be resizing at
// all, just coloring.
if ($xRatio * $height < $maxHeight) { // Resize the image based on width
$tnHeight = ceil($xRatio * $height);
$tnWidth = $maxWidth;
} else {
// Resize the image based on height
$tnWidth = ceil($yRatio * $width);
$tnHeight = $maxHeight;
}
if ((int)ini_get('memory_limit') < 100) {
ini_set('memory_limit', '100M');
}
ImageGD::resize($this->imagePath, $tnWidth, $tnHeight, $offsetX, $offsetY, $width, $height)
->quality(100)
->output($this->imageCroppedPath);
}
protected function calculateMaxes($width, $height)
{
$maxWidth = ($this->width !== false) ? (int)$this->width : 0;
$maxHeight = ($this->height !== false) ? (int)$this->height : 0;
if (!$maxWidth && $maxHeight) {
$maxWidth = 99999999999999;
} elseif ($maxWidth && !$maxHeight) {
$maxHeight = 99999999999999;
} elseif (!$maxWidth && !$maxHeight) {
$maxWidth = $width;
$maxHeight = $height;
}
return [$maxWidth, $maxHeight];
}
protected function calculateCrop($width, $height, $offsetX, $offsetY)
{
if ($this->cropRatio !== false) {
$cropRatio = explode(':', (string)$this->cropRatio);
if (count($cropRatio) == 2) {
$ratioComputed = $width / $height;
$cropRatioComputed = (float)$cropRatio[0] / (float)$cropRatio[1];
if ($ratioComputed < $cropRatioComputed) { // Image is too tall so we will crop the top and bottom
$origHeight = $height;
$height = $width / $cropRatioComputed;
$offsetY = ($origHeight - $height) / 2;
} else {
if ($ratioComputed > $cropRatioComputed) { // Image is too wide so we will crop off the left and right sides
$origWidth = $width;
$width = $height * $cropRatioComputed;
$offsetX = ($origWidth - $width) / 2;
}
}
}
}
return [$width, $height, $offsetX, $offsetY];
}
protected function watermarkedImage($from)
{
$filename = sha1(basename($this->imagePath) . $this->width . $this->height . $this->cropRatio . $this->showWatermark);
$path = $this->getNestedDir($filename);
$this->imageCroppedPath = Yii::web()->uploadSaver->uploadsPath . '/' . $path . '/' . $filename . '.' . $this->getExt();
if (!file_exists($this->imageCroppedPath)) {
$this->watermarkImage($from);
}
}
public function watermarkImage($from)
{
if ((int)ini_get('memory_limit') < 100) {
ini_set('memory_limit', '100M');
}
$wmPath = is_callable($this->params['watermarkPath']) ? $this->params['watermarkPath']() : $this->params['watermarkPath'];
ImageGD::watermark($from, $wmPath,
$this->params['watermarkPosition'] ?? false)->output($this->imageCroppedPath);
}
/**
* @param string $image
* @param int|boolean $width
* @param int|boolean $height
* @param string|boolean $cropRatio
* @param array $options
* @return string
*/
public static function render($image, $width = false, $height = false, $cropRatio = false, $options = [])
{
if (strpos($image, '//') === 0 || preg_match('/https?:/', $image)) {
return CHtml::image($image, $options['alt'] ?? '', $options);
}
if (empty($image) || !file_exists(Yii::web()->uploadSaver->uploadsPath . '/..' . $image)) {
return '';
}
$options = \CMap::mergeArray([
'image' => $image,
'width' => $width,
'height' => $height,
'cropRatio' => $cropRatio,
], $options);
return (new static($options))->printHtml($options);
}
protected function printHtml($options)
{
$alt = '';
if (isset($options['alt'])) {
$alt = $options['alt'];
unset($options['alt']);
}
$htmlOptions = [];
if (isset($options['class'])) {
$htmlOptions['class'] = $options['class'];
}
if (isset($options['style'])) {
$htmlOptions['style'] = $options['style'];
}
return CHtml::image(Yii::web()->baseUrl . '/'
. ltrim(Yii::web()->uploadSaver->uploadsUrl, '/') . '/'
. $this->getNestedDir(basename($this->imageCroppedPath)) . '/'
. basename($this->imageCroppedPath), $alt, $htmlOptions);
}
public static function getImageUrl($image, $width = false, $height = false, $cropRatio = false, $options = [])
{
if (empty($image) || !file_exists(Yii::web()->uploadSaver->uploadsPath . '/..' . $image)) {
return '';
}
$options = \CMap::mergeArray([
'image' => $image,
'width' => $width,
'height' => $height,
'cropRatio' => $cropRatio,
], $options);
return (new static($options))->getUrl();
}
protected function getUrl()
{
return Yii::web()->baseUrl . '/'
. ltrim(Yii::web()->uploadSaver->uploadsUrl, '/') . '/'
. $this->getNestedDir(basename($this->imageCroppedPath)) . '/'
. basename($this->imageCroppedPath);
}
}