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, написанием её разных вариантов мы и займёмся.

Параметры функции следующие:

Пятый и шестой параметры можно не передавать, примем фоновый цвет по умолчанию белым, а качество генерируемого рисунка JPEG равным 90%.

Функция tumbmaker для варианта 1 масштабирования рисунка
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;
}

Маленькие картинки при этом останутся маленькими и масштабироваться не будут.

Функция tumbmaker для варианта 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;
 $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>.

Это некрасиво, так что приводить код не будем.

Рейтинг@Mail.ru

вверх гостевая; E-mail
Hosted by uCoz