res = null; } /** * Close * * Destroy image resource */ public function close() { if (is_resource($this->res)) { imagedestroy($this->res); } if ($this->memory_limit) { ini_set('memory_limit', $this->memory_limit); } } /** * Load image * * Loads an image content in memory and set {@link $res} property. * * @param string $f Image file path */ public function loadImage($f) { if (!file_exists($f)) { throw new Exception('Image doest not exists'); } if (($info = @getimagesize($f)) !== false) { $this->memoryAllocate( $info[0], $info[1], isset($infos['channels']) ? $info['channels'] : 4 ); switch ($info[2]) { case 3: // PNG $this->res = @imagecreatefrompng($f); if (is_resource($this->res)) { @imagealphablending($this->res, false); @imagesavealpha($this->res, true); } break; case 2: // JPEG $this->res = @imagecreatefromjpeg($f); break; case 1: // GIF $this->res = @imagecreatefromgif($f); break; case 18: // WEBP if (function_exists('imagecreatefromwebp')) { $this->res = @imagecreatefromwebp($f); if (is_resource($this->res)) { @imagealphablending($this->res, false); @imagesavealpha($this->res, true); } } else { throw new Exception('WebP image format not supported'); } break; } } if (!is_resource($this->res)) { throw new Exception('Unable to load image'); } } /** * Image width * * @return integer Image width */ public function getW() { return imagesx($this->res); } /** * Image height * * @return integer Image height */ public function getH() { return imagesy($this->res); } public function memoryAllocate($w, $h, $bpp = 4) { $mem_used = function_exists('memory_get_usage') ? @memory_get_usage() : 4000000; $mem_limit = @ini_get('memory_limit'); if ($mem_limit && trim($mem_limit) === '-1' || !files::str2bytes($mem_limit)) { // Cope with memory_limit set to -1 in PHP.ini return; } if ($mem_used && $mem_limit) { $mem_limit = files::str2bytes($mem_limit); $mem_avail = $mem_limit - $mem_used - (512 * 1024); $mem_needed = $w * $h * $bpp; if ($mem_needed > $mem_avail) { if (@ini_set('memory_limit', $mem_limit + $mem_needed + $mem_used) === false) { throw new Exception(__('Not enough memory to open image.')); } if (!$this->memory_limit) { $this->memory_limit = $mem_limit; } } } } /** * Image output * * Returns image content in a file or as HTML output (with headers) * * @param string $type Image type (png or jpg) * @param string|null $file Output file. If null, output will be echoed in STDOUT * @param integer $qual JPEG image quality */ public function output($type = 'png', $file = null, $qual = 90) { if (!$file) { header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0'); header('Pragma: no-cache'); switch (strtolower($type)) { case 'png': header('Content-type: image/png'); imagepng($this->res); return true; case 'jpeg': case 'jpg': header('Content-type: image/jpeg'); imagejpeg($this->res, null, $qual); return true; case 'wepb': if (function_exists('imagewebp')) { header('Content-type: image/webp'); imagewebp($this->res, null, $qual); return true; } return false; default: return false; } } elseif (is_writable(dirname($file))) { switch (strtolower($type)) { case 'png': return imagepng($this->res, $file); case 'jpeg': case 'jpg': return imagejpeg($this->res, $file, $qual); case 'webp': if (function_exists('imagewebp')) { return imagewebp($this->res, $file, $qual); } return false; default: return false; } } return false; } /** * Resize image * * @param mixed $WIDTH Image width (px or percent) * @param mixed $HEIGHT Image height (px or percent) * @param string $MODE Crop mode (force, crop, ratio) * @param boolean $EXPAND Allow resize of image */ public function resize($WIDTH, $HEIGHT, $MODE = 'ratio', $EXPAND = false) { $imgWidth = $this->getW(); $imgHeight = $this->getH(); if (strpos($WIDTH, '%', 0)) { $WIDTH = $imgWidth * $WIDTH / 100; } if (strpos($HEIGHT, '%', 0)) { $HEIGHT = $imgHeight * $HEIGHT / 100; } $ratio = $imgWidth / $imgHeight; // guess resize ($_w et $_h) if ($MODE == 'ratio') { $_w = 99999; if ($HEIGHT > 0) { $_h = $HEIGHT; $_w = $_h * $ratio; } if ($WIDTH > 0 && $_w > $WIDTH) { $_w = $WIDTH; $_h = $_w / $ratio; } if (!$EXPAND && $_w > $imgWidth) { $_w = $imgWidth; $_h = $imgHeight; } } else { // crop source image $_w = $WIDTH; $_h = $HEIGHT; } if ($MODE == 'force') { if ($WIDTH > 0) { $_w = $WIDTH; } else { $_w = $HEIGHT * $ratio; } if ($HEIGHT > 0) { $_h = $HEIGHT; } else { $_h = $WIDTH / $ratio; } if (!$EXPAND && $_w > $imgWidth) { $_w = $imgWidth; $_h = $imgHeight; } $cropW = $imgWidth; $cropH = $imgHeight; $decalW = 0; $decalH = 0; } else { // guess real viewport of image $innerRatio = $_w / $_h; if ($ratio >= $innerRatio) { $cropH = $imgHeight; $cropW = $imgHeight * $innerRatio; $decalH = 0; $decalW = ($imgWidth - $cropW) / 2; } else { $cropW = $imgWidth; $cropH = $imgWidth / $innerRatio; $decalW = 0; $decalH = ($imgHeight - $cropH) / 2; } } if ($_w < 1) { $_w = 1; } if ($_h < 1) { $_h = 1; } # truecolor is 24 bit RGB, ie. 3 bytes per pixel. $this->memoryAllocate($_w, $_h, 3); $dest = imagecreatetruecolor($_w, $_h); $fill = imagecolorallocate($dest, 128, 128, 128); imagefill($dest, 0, 0, $fill); @imagealphablending($dest, false); @imagesavealpha($dest, true); imagecopyresampled($dest, $this->res, 0, 0, $decalW, $decalH, $_w, $_h, $cropW, $cropH); imagedestroy($this->res); $this->res = $dest; return true; } }