Pers.narod.ru. PHP. Статьи. PHP: 3 способа масштабирования рисунка при загрузке |
Загрузка рисунков на сервер с их предварительным масштабированием - одна из самых распространённых задач,
которые решает PHP-программист. Несложный код для загрузки файлов приводился, например, в
этой статье. Вот типовой фрагмент, вызывающий для загрузки
отмасштабированного
рисунка некую ещё не написанную функцию tumbmaker
, в зависимости
от того, доступна ли библиотека GdLib и включена ли настройка, указывающая её использовать:
define("MAX_WIDTH","176"); //Ширина картинки define("MAX_HEIGHT","132"); //Высота картинки define("USE_GDLIB","1"); //Использовать библиотеку GDLib (php_gd2.dll) для масштабирования изображений // ... if (!empty($_FILES['url']['tmp_name'])) { $file = $_FILES['url']['tmp_name']; $filename = strtolower($_FILES['url']['name']); //Получить новое имя рисунка - на самом деле бывает нужно переименовать, //избавиться от кириллицы в имени и т.п. $size = getimagesize($file); $width = $size[0]; $height = $size[1]; if ($width!=MAX_WIDTH or $height!=MAX_HEIGHT) { $ver = gdVersion(); if (USE_GDLIB=='1') { if ($ver>1) { $r=tumbmaker ($file,$filename,MAX_WIDTH,MAX_HEIGHT); if (!$r) { $error .= '<br>Не удалось программно изменить изображение. Пожалуйста, проверьте работу библиотеки GBLib или загрузите картинку меньшего размера. Установки из настроек сайта: ширина '.MAX_WIDTH.', высота '.MAX_HEIGHT.' пикс.'; } } else { $error .= '<br>В настройках сайта включено масштабирование изображений, но библиотека GDLib версии 2 недоступна. Пожалуйста, настройте её или загрузите картинку другого размера. Установки из настроек сайта: ширина '.MAX_WIDTH.', высота '. MAX_HEIGHT.' пикс.'; } } else { $error .= '<br>Не совпадает размер рисунка. Установки из настроек сайта: ширина '.MAX_WIDTH.', высота '.MAX_HEIGHT. ' пикс. Автоматическое масштабирование изображений: выключено'; } } }
Функция gdVersion
определяет версию установленной библиотеки GdLib, для работы функций
масштабирования изображений нужна версия не ниже 2. Код функции есть в статье.
Здесь мы обратим внимание на саму задачу масштабирования рисунка, тем более, что понимать её можно по-разному. Я вижу как минимум три возможности:
1. Скрипт масштабирует рисунок без нарушения пропорций или обрезания сторон так, чтобы он вписался в предустановленный размер. Так как ширина и высота исходного рисунка могут быть любыми, по одной из осей может остаться свободное место. Так я делаю обычно по умолчанию, так как искажение или обрезание рисунков не предполагается, если специально не оговорено заказчиком.
2. Скрипт обрезает рисунок так, чтобы соблюдались пропорции целевого рисунка, а затем масштабирует. При этом некоторая часть изображения может "пропасть", особенно если пропорции исходного рисунка сильно отличаются от целевых.
3. Скрипт приводит рисунок к целевому размеру, невзирая на пропорции. Так поступает браузер, если указать в HTML-коде точные размеры рисунка, не соответствующие реальным. При этом рисунок может быть искажён в смысле пропорций.
Вот схематическое изображение всех 3 вариантов:
Разумеется, существуют другие возможности, например, вообще не давать загружать рисунки "неправильных" размеров.
Основную работу по масштабированию картинки выполнит функция tumbmaker
, написанием её разных вариантов мы и займёмся.
Параметры функции следующие:
$src
- путь к исходному файлу;
$dest
- путь к целевому файлу;
$max_width
, $max_height
- ширина и высота целевой области, в которую нужно вписать рисунок;
$rgb
- фоновый цвет полотна целевого рисунка, RGB-код цвета;
$quality
- качество выходного JPEG-рисунка, число от 0 до 100 (проценты).Пятый и шестой параметры можно не передавать, примем фоновый цвет по умолчанию белым, а качество генерируемого рисунка JPEG равным 90%.
function tumbmaker ($src, $dest, $max_width, $max_height, $rgb=0xFFFFFF, $quality=90) { if (!file_exists($src)) return false; $size = getimagesize($src); if ($size === false) return false; $format = strtolower(substr($size['mime'], strpos($size['mime'], '/')+1)); $icfunc = 'imagecreatefrom'.$format; if (!function_exists($icfunc)) return false; $x_ratio = $max_width / $size[0]; $y_ratio = $max_height / $size[1]; $ratio = min($x_ratio, $y_ratio); $use_x_ratio = ($x_ratio == $ratio); $new_width = $use_x_ratio ? $max_width : floor($size[0] * $ratio); $new_height = !$use_x_ratio ? $max_height : floor($size[1] * $ratio); $new_left = $use_x_ratio ? 0 : floor(($max_width - $new_width) / 2); $new_top = !$use_x_ratio ? 0 : floor(($max_height - $new_height) / 2); $isrc = $icfunc($src); $idest = imagecreatetruecolor($max_width, $max_height); imagefill($idest, 0, 0, $rgb); imagecopyresampled($idest, $isrc, $new_left, $new_top, 0, 0, $new_width, $new_height, $size[0], $size[1]); imagejpeg($idest, $dest, $quality); imagedestroy($isrc); imagedestroy($idest); return true; }
Маленькие картинки просто разместятся по центру созданного полотна, большие - масштабируются, возможно, оставляя слева и справа или сверху и снизу свободное пространство, закрашенное фоновым цветом.
Если мы хотим, чтобы полотно максимального размера не создавалось в обязательном порядке - то есть, мы просто пропорционально масштабируем картинку так, чтобы она не превышала целевого размера ни по одной из сторон, в функции изменится лишь 2 строки (и уберутся 2 лишних):
function tumbmaker ($src, $dest, $max_width, $max_height, $rgb=0xFFFFFF, $quality=90) { if (!file_exists($src)) return false; $size = getimagesize($src); if ($size === false) return false; $format = strtolower(substr($size['mime'], strpos($size['mime'], '/')+1)); $icfunc = 'imagecreatefrom'.$format; if (!function_exists($icfunc)) return false; $x_ratio = $max_width / $size[0]; $y_ratio = $max_height / $size[1]; $ratio = min($x_ratio, $y_ratio); $use_x_ratio = ($x_ratio == $ratio); $new_width = $use_x_ratio ? $max_width : floor($size[0] * $ratio); $new_height = !$use_x_ratio ? $max_height : floor($size[1] * $ratio); //$new_left, $new_top теперь не нужны $isrc = $icfunc($src); $idest = imagecreatetruecolor($new_width, $new_height); //изменено imagefill($idest, 0, 0, $rgb); imagecopyresampled($idest, $isrc, 0, 0, 0, 0, $new_width, $new_height, $size[0], $size[1]); //изменено imagejpeg($idest, $dest, $quality); imagedestroy($isrc); imagedestroy($idest); return true; }
Маленькие картинки при этом останутся маленькими и масштабироваться не будут.
function tumbmaker ($src, $dest, $max_width, $max_height, $rgb=0xFFFFFF, $quality=90) { if (!file_exists($src)) return false; $size = getimagesize($src); if ($size === false) return false; $src_width=$size[0]; $src_height=$size[1]; $src_left = $src_top = 0; $src_copy_width = $src_width; $src_copy_height = $src_height; $dw=$max_width/$src_width; $dh=$max_height/$src_height; if ($dw<$dh) { //обрез.по ширине $src_copy_width=round($src_height*$max_width/$max_height); $src_left=round(($src_width-$src_copy_width)/2); } else { //обрез.по высоте $src_copy_height=round($src_width*$max_height/$max_width); $src_top=round(($src_height-$src_copy_height)/2); } $format = strtolower(substr($size['mime'], strpos($size['mime'], '/')+1)); $icfunc = 'imagecreatefrom'.$format; if (!function_exists($icfunc)) return false; $isrc = $icfunc($src); $idest = imagecreatetruecolor($max_width, $max_height); imagefill($idest, 0, 0, $rgb); imagecopyresampled($idest, $isrc, 0, 0, $src_left, $src_top, $max_width, $max_height, $src_copy_width, $src_copy_height); imagejpeg($idest, $dest, $quality); imagedestroy($isrc); imagedestroy($idest); return true; }
Маленькая картинка этим кодом тоже растянется и обрежется.
В варианте 3 просто принудительно указываются нужные размеры - в функции масштабирования
или же атрибутами width
и height
тега рисунка <img>
.
Это некрасиво, так что приводить код не будем.
гостевая; E-mail |