Довольно давно работаю в веб-студии, занимаемся разработкой сайтов в back-end’ом на php. Практически на каждом проекте используется «универсальный» ужиматель картинок, основными целями которого являются уменьшение объема загружаемых данных и избавление вносящего контент от мыслей о правильных пропорциях изображений.
Постепенно скрипт модернизировался, на данный момент постарался сделать его максимально удобным и быстрым в подключении к любому сайту. Основные возможности:
— ресайз jpg, png, gif;
— возможность задания ширины и высоты сжатого изображения либо только одного из параметров, второй будет подсчитан пропорционально от исходного изображения;
— три вида ресайзинга (добавление полос — определенного цвета или прозрачных, обрезка изображения);
— кеширование обработанных картинок.
Примеры и код под катом.
Для работы ресайзера используется собственно сам скрипт и файл .htaccess для более простого задания адресов картинок. В принципе, можно обойтись и без последнего, но тогда атрибут src у изображений будет несколько страшным.
В случае использования htaccess вызов ресайзера выглядит следующим образом:
image/<resize_type>/<new_width>/[new_height]/<img_src>
Где:
- resize_type — обязательный параметр, принимает значения b — borders, t — transparent, c — crop;
- new_width — обязательный параметр, ширина нового изображения в пикселах. Если указан 0 — посчитает ширину изображения автоматически, исходя из высоты нового изображения с сохранением пропорций. В этом случае, поскольку полученная картинка будет полностью пропорциональна исходной выбор вида ресайзинга не играет никакой роли. Использование нуля актуально для горизонтальных слайдеров, высота которых должна быть фиксирована;
- new_height — необязательный параметр высоты нового изображения. Если его не указать или указать 0 — посчитает автоматически с сохранением пропорций;
- img_src — путь к картинке.
Собственно, примеры работы в различных режимах с одним и тем же исходным изображением. Размер исходной картинки — 450х411 пикселей.
Ресайз с добавлением полос к размеру 300х200 (image/b/300/200/img_1.jpg):
Работа ресайзера в данном случае простая. Сначала определяется, какая из сторон имеет больший коэффициент сжатия: 450/300 = 1.5 и 411/200 = 2.055. Затем изображение уменьшается в 2.055 раза по обоим параметрам, в результате чего получаем картинку в размере 219х200 и добавляются полосы слева и справа до заданных 300 пикселей. Аналогичным образом будет выглядеть и использование параметра t, так как формат сохраняемого в кеше изображения совпадает с исходным, а правильное его отображение (с прозрачностью) достигается за счет передачи header’ов для png изображений.
Ресайз с пропорциональным обрезанием к размеру 300х200 (image/c/300/200/img_1.jpg):
В данном случае будет выбран минимальный из коэффициентов сжатия, в данном случае — 1.5. Затем изображение уменьшается в 1.5 раза по обоим параметрам, что дает на выходе 300х274, а затем лишние 74 будут обрезаны — по 37 сверху и снизу.
Если не указать параметр высоты, оставив только ширину, то она будет рассчитана автоматически. К примеру, для ширины 300 — это 2/3 от ширины исходного изображения, значит и новая высота должна составить 2/3 от исходных 411, а конкретно 274 (image/b/300/img_1.jpg):
Аналогичным образом, если указать ширину равной нулю, то получим её автоматический расчет (image/b/0/300/img_1.jpg):
<? error_reporting( 0 ); //цвет "полос" по бокам $color = array( 255, 255, 255 ); $file_name = $_GET["src"]; list( $width, $height, $ext ) = getimagesize( $file_name ); //задаем новые ширину и высоту $params["width"] = (int)$_GET["w"]; if( !isset( $_GET["h"] ) || 0 == (int)$_GET["h"] ){ $params["height"] = $height * $params["width"]/$width; } else { $params["height"] = (int)$_GET["h"]; } if( 0 == $params["width"] ){ $params["width"] = $width * $params["height"]/$height; } //папка с кешем изображений. Внутри img_cache/ повторяется полный путь исходного изображения $cache_file_folder = "img_cache/" . substr( $file_name, 0, strrpos( $file_name, "/" ) ); $cache_file_name = "img_cache/" . substr( $file_name, 0, strrpos( $file_name, "." ) ) . "_" . $_GET["resize_type"] . "_" . $params["width"] . "_" . $params["height"] . substr( $file_name, strrpos( $file_name, "." ) ); //проверка наличия изображения в кеше. Если оно есть и было создано после последнего изменения исходного изображения - берем его if( file_exists( $cache_file_name ) ){ if( filemtime( $cache_file_name ) > filemtime( $file_name ) ){ if( 1 == $ext ){ header( "Content-type: " . image_type_to_mime_type( IMAGETYPE_GIF ) ); } else if( 2 == $ext ){ header( "Content-type: " . image_type_to_mime_type( IMAGETYPE_JPEG ) ); } else if( 3 == $ext ){ header( "Content-type: " . image_type_to_mime_type( IMAGETYPE_PNG ) ); } //обновление времени последнего изменения. Используется, если необходима очистка давно не запрашиваемых картинок touch( $cache_file_name ); echo file_get_contents( $cache_file_name ); exit(); } } //пытаемся создать папку для кеша mkdir( $cache_file_folder, 0755, true ); //непосредственно код ресайзинга switch( $_GET["resize_type"] ){ case "b": if( 1 == $ext ){ header( "Content-type: " . image_type_to_mime_type( IMAGETYPE_GIF ) ); $image = imagecreatefromgif( $file_name ); } else if( 2 == $ext ){ header( "Content-type: " . image_type_to_mime_type( IMAGETYPE_JPEG ) ); $image = imagecreatefromjpeg( $file_name ); } else if( 3 == $ext ){ header( "Content-type: " . image_type_to_mime_type( IMAGETYPE_PNG ) ); $image = imagecreatefrompng( $file_name ); } $new_width = (int)$params["width"]; $new_height = (int)$params["height"]; if( $new_width == 0 || $new_height == 0 || !$image || !in_array( $ext, array( 1, 2, 3 ) ) ){ $image_new = imagecreatetruecolor( 100, 30 ); $bgc = imagecolorallocatealpha( $image_new, $color[0], $color[1], $color[2], 127 ); $tc = imagecolorallocate( $image_new, 0, 0, 0 ); imagefilledrectangle( $image_new, 0, 0, 100, 30, $bgc ); imagestring( $image_new, 1, 5, 5, "Error loading", $tc ); if( 1 == $ext ){ imagegif( $image_new ); imagedestroy( $image_new ); } else if( 2 == $ext ){ imagejpeg( $image_new ); imagedestroy( $image_new ); } else if( 3 == $ext ){ imagepng( $image_new ); imagedestroy( $image_new ); } exit(); } $image_new = imagecreatetruecolor( $new_width, $new_height ); imagealphablending( $image_new, false ); imagesavealpha( $image_new, true ); $bgc = imagecolorallocatealpha( $image_new, $color[0], $color[1], $color[2], 127 ); imagefilledrectangle( $image_new, 0, 0, $new_width, $new_height, $bgc ); if( $new_width/$new_height > $width/$height ){ $ins = $width*($new_height/$height); $out = ( $new_width - $ins )/2; imagecopyresampled( $image_new, $image, $out, 0, 0, 0, $ins, $new_height, $width, $height ); } else { $ins = $height*($new_width/$width); $out = ( $new_height - $ins )/2; imagecopyresampled( $image_new, $image, 0, $out, 0, 0, $new_width, $ins, $width, $height ); } if( 1 == $ext ){ imagegif( $image_new ); imagegif( $image_new, $cache_file_name ); imagedestroy( $image_new ); } else if( 2 == $ext ){ imagejpeg( $image_new ); imagejpeg( $image_new, $cache_file_name ); imagedestroy( $image_new ); } else if( 3 == $ext ){ imagepng( $image_new ); imagepng( $image_new, $cache_file_name ); imagedestroy( $image_new ); } break; case "t": if( 1 == $ext ){ $image = imagecreatefromgif( $file_name ); } else if( 2 == $ext ){ $image = imagecreatefromjpeg( $file_name ); } else if( 3 == $ext ){ $image = imagecreatefrompng( $file_name ); } header( "Content-type: " . image_type_to_mime_type( IMAGETYPE_PNG ) ); $new_width = (int)$params["width"]; $new_height = (int)$params["height"]; if( $new_width == 0 || $new_height == 0 || !$image || !in_array( $ext, array( 1, 2, 3 ) ) ){ $image_new = imagecreatetruecolor( 100, 30 ); $bgc = imagecolorallocatealpha( $image_new, $color[0], $color[1], $color[2], 127 ); $tc = imagecolorallocate( $image_new, 0, 0, 0 ); imagefilledrectangle( $image_new, 0, 0, 100, 30, $bgc ); imagestring( $image_new, 1, 5, 5, "Error loading", $tc ); if( 1 == $ext ){ imagegif( $image_new ); imagedestroy( $image_new ); } else if( 2 == $ext ){ imagejpeg( $image_new ); imagedestroy( $image_new ); } else if( 3 == $ext ){ imagepng( $image_new ); imagedestroy( $image_new ); } exit(); } $image_new = imagecreatetruecolor( $new_width, $new_height ); imagealphablending( $image_new, false ); imagesavealpha( $image_new, true ); $bgc = imagecolorallocatealpha( $image_new, $color[0], $color[1], $color[2], 127 ); imagefilledrectangle( $image_new, 0, 0, $new_width, $new_height, $bgc ); if( $new_width/$new_height > $width/$height ){ $ins = $width*($new_height/$height); $out = ( $new_width - $ins )/2; imagecopyresampled( $image_new, $image, $out, 0, 0, 0, $ins, $new_height, $width, $height ); } else { $ins = $height*($new_width/$width); $out = ( $new_height - $ins )/2; imagecopyresampled( $image_new, $image, 0, $out, 0, 0, $new_width, $ins, $width, $height ); } imagepng( $image_new ); imagepng( $image_new, $cache_file_name ); imagedestroy( $image_new ); break; case "c": if( 1 == $ext ){ header( "Content-type: " . image_type_to_mime_type( IMAGETYPE_GIF ) ); $image = imagecreatefromgif( $file_name ); } else if( 2 == $ext ){ header( "Content-type: " . image_type_to_mime_type( IMAGETYPE_JPEG ) ); $image = imagecreatefromjpeg( $file_name ); } else if( 3 == $ext ){ header( "Content-type: " . image_type_to_mime_type( IMAGETYPE_PNG ) ); $image = imagecreatefrompng( $file_name ); } $new_width = (int)$params["width"]; $new_height = (int)$params["height"]; if( $new_width == 0 || $new_height == 0 || !$image || !in_array( $ext, array( 1, 2, 3 ) ) ){ $image_new = imagecreatetruecolor( 100, 30 ); $bgc = imagecolorallocate( $image_new, 255, 255, 255 ); $tc = imagecolorallocate( $image_new, 0, 0, 0 ); imagefilledrectangle( $image_new, 0, 0, 100, 30, $bgc ); imagestring( $image_new, 1, 5, 5, "Error loading", $tc ); if( 1 == $ext ){ imagegif( $image_new ); imagedestroy( $image_new ); } else if( 2 == $ext ){ imagejpeg( $image_new ); imagedestroy( $image_new ); } else if( 3 == $ext ){ imagepng( $image_new ); imagedestroy( $image_new ); } exit(); } $image_new = imagecreatetruecolor( $new_width, $new_height ); imagealphablending( $image_new, false ); imagesavealpha( $image_new, true ); $width/$new_width < $height/$new_height ? $coef = $width/$new_width : $coef = $height/$new_height; $start_x = ( $width - $new_width*$coef )/2; $start_y = ( $height - $new_height*$coef )/2; $end_x = $width - 2*$start_x; $end_y = $height - 2*$start_y; imagecopyresampled( $image_new, $image, 0, 0, $start_x, $start_y, $new_width, $new_height, $end_x, $end_y ); if( 1 == $ext ){ imagegif( $image_new ); imagegif( $image_new, $cache_file_name ); imagedestroy( $image_new ); } else if( 2 == $ext ){ imagejpeg( $image_new ); imagejpeg( $image_new, $cache_file_name ); imagedestroy( $image_new ); } else if( 3 == $ext ){ imagepng( $image_new ); imagepng( $image_new, $cache_file_name ); imagedestroy( $image_new ); } break; }
.htaccess:
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^image/([a-z])/([0-9]+)/([0-9]+)/([A-z0-9-\/\.]+)$ image.php?resize_type=$1&w=$2&h=$3&src=$4 [QSA,L] RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^image/([a-z])/([0-9]+)/([A-z0-9-\/\.]+)$ image.php?resize_type=$1&w=$2&src=$4 [QSA,L] </IfModule>
Спасибо за внимание. Надеюсь, скрипт кому-нибудь да пригодится.
ссылка на оригинал статьи http://habrahabr.ru/post/257719/
Добавить комментарий