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); } }