Сейчас очень много всякого рода плагинов галерей и так далее, но не во всех CRM есть удобные модули (плагины) что бы удобно загружать изображения. Или просто человек который заполняет сайт не утруждается оптимизацией изображений (заливает как есть) и утяжеляет страницу.
Для одной задачи понадобилось изменять размер изображений на лету для вывода превью картинки. Нашел хорошее решение на одном из форумов. Спасибо автору и сохраню у себя на память.
И так:
Если нам необходимо изменить размер изображения мы просто указываем необходимые параметры в адресе изображения.
... src="/images/image.jpg?w=250&h=250" ...
Все остальное за нас делает простой класс на PHP :
class Thumbnail { private $w; private $h; private $filename; private $crop; private $_mime_settings; private $_fsave_allowed; private $_tname_tpl = '%s_%sx%s'; private $_default_width = 250; private $_default_height = 250; private $_jpeg_quality = 75; private $_sess_varname = 'THUMB'; public function __construct() { session_start(); $this->w = abs((int)@$_GET['w']); $this->h = abs((int)@$_GET['h']); if (!$this->w && !$this->h) { # вписать в рамку по умолчанию $this->w = $this->_default_width; $this->h = $this->_default_height; } $this->filename = @$_GET['name']; $this->crop = isset($_GET['c']) || isset($_GET['tc']); $this->_mime_settings = array( 'image/gif' => array( 'ext' => '.gif', 'create' => 'imagecreatefromgif', 'save' => array(&$this, '_gif_save'), ), 'image/jpeg' => array( 'ext' => '.jpg', 'create' => 'imagecreatefromjpeg', 'save' => array(&$this, '_jpeg_save'), ), 'image/pjpeg' => array( 'ext' => '.jpg', 'create' => 'imagecreatefromjpeg', 'save' => array(&$this, '_jpeg_save'), ), 'image/png' => array( 'ext' => '.png', 'create' => 'imagecreatefrompng', 'save' => array(&$this, '_png_save'), ), ); $this->_fsave_allowed = isset($_SESSION[$this->_sess_varname]); $this->_run(); } private function _run() { if (!file_exists($this->filename) || !is_file($this->filename)) exit; $info = getimagesize($this->filename); if (!$info || !isset($this->_mime_settings[$info['mime']])) { # можно возвращать дефолтную картинку # .. и удалять лишние картинки #$files = glob("{$name}_*{$ext}"); #glob("*.txt") exit; } $settings =& $this->_mime_settings[$info['mime']]; $orig_width = $info[0]; $orig_height = $info[1]; $dst_x = $dst_y = 0; if (!$this->w) { # вписываем по высоте $new_width = $this->w = floor($orig_width * $this->h / $orig_height); $new_height = $this->h; } elseif (!$this->h) { # вписываем по ширине $new_width = $this->w; $new_height = $this->h = floor($orig_height * $this->w / $orig_width); } elseif ($this->crop) { # вписываем с обрезкой $scaleW = $this->w / $orig_width; $scaleH = $this->h / $orig_height; $scale = max($scaleW, $scaleH); $new_width = floor($orig_width * $scale); $new_height = floor($orig_height * $scale); $dst_x = floor(($this->w - $new_width) / 2); $dst_y = floor(($this->h - $new_height) / 2); } else { # вписываем без обрезки $scaleW = $this->w / $orig_width; $scaleH = $this->h / $orig_height; $scale = min($scaleW, $scaleH); $new_width = $this->w = floor($orig_width * $scale); $new_height = $this->h = floor($orig_height * $scale); } if ($this->w > $orig_width || $this->h > $orig_height) { header('Content-type: ' . $info['mime']); readfile($this->filename); exit; } $thumbFilename = dirname($this->filename) . '/' . sprintf($this->_tname_tpl, basename($this->filename, $settings['ext']), $this->w, $this->h) . $settings['ext'] ; if (file_exists($thumbFilename) && filemtime($thumbFilename) >= filemtime($this->filename)) { header('Content-type: ' . $info['mime']); readfile($thumbFilename); exit; } $orig_img = call_user_func($settings['create'], $this->filename); $tmp_img = imagecreatetruecolor($this->w, $this->h); # Copy and resize old image into new image imagecopyresampled( $tmp_img, $orig_img, $dst_x, $dst_y, 0, 0, $new_width, $new_height, $orig_width, $orig_height ); imagedestroy($orig_img); header('Content-type: ' . $info['mime']); call_user_func($settings['save'], $tmp_img, $thumbFilename); imagedestroy($tmp_img); exit; } private function _gif_save($img, $filename = false) { if ($filename !== false && $this->_fsave_allowed) imagegif($img, $filename); imagegif($img); } private function _jpeg_save($img, $filename = false) { if ($filename !== false && $this->_fsave_allowed) imagejpeg($img, $filename, $this->_jpeg_quality); imagejpeg($img, null, $this->_jpeg_quality); } private function _png_save($img, $filename = false) { if ($filename !== false && $this->_fsave_allowed) imagepng($img, $filename); imagepng($img); } } new Thumbnail;
И так что бы наш класс заработал, сохраним его например в каталог includes в файл class.Thumbnail.php и добавим пару строк в .htaccess:
RewriteEngine On RewriteRule ^includes/class.Thumbnail.php$ includes/class.Thumbnail.php [L] RewriteCond %{QUERY_STRING} w=[0-9]+ [OR] RewriteCond %{QUERY_STRING} h=[0-9]+ [OR] RewriteCond %{QUERY_STRING} ^tc?$ RewriteRule ^(.*)\.(jpg|gif|png) includes/class.Thumbnail.php?name=%{REQUEST_FILENAME}&%{QUERY_STRING} [NC,L]
А вот если у вас стоит связка NGINX + APACHE и nginx настрое на отдачу статики то или вы убираете из правила где отдается статика jpg|gif|png или в это правило вставляете:
rewrite ^/includes/class.Thumbnail.php$ /includes/class.Thumbnail.php last; if ($args ~ "w=[0-9]+"){ set $rule_1 1; } if ($args ~ "h=[0-9]+"){ set $rule_1 1; } if ($args ~ "^tc?$"){ set $rule_1 1; } if ($rule_1 = "1"){ rewrite ^/(.*).(jpg|gif|png) /includes/class.Thumbnail.php?name=$request_filename&$args last; }
Параметры GET для работы с изображением:
?[w=xx][h=xx][c]|[t[c]]
w (width) - ширина, в которую надо вписать
h (height) - высота, в которую надо вписать
Если указан только один параметр, то сделает по нему, например картинку надо вписать в высоту 100, тогда пишем ?h=100 и все.
Если вписать без обрезки в рамку, например 150х100, то пишем ?w=150&h=100 --- впишет по максимальной подходящей размерности
Если нужно "жестко" вписать в рамку, например сделать картинку 100х100, чтоб заполняла все пространство (обрезка), то пишем ?w=100&h=100&c
?t - вписывание в рамку по умолчанию
?tc - обрезка по рамке с размерами по умолчанию
Так же есть вариант записи на диск:
Запись превью на диск разрешается, если в сессии определена переменная THUMB
Данное решение работает на GD, зато простое и работает, и все что остается после настройки так это внести изменения в url изображений