Автоматизируем уменьшение и обрезку изображений

Автоматизируем уменьшение и обрезку изображений


Сегодня мы будем писать скрипт на PHP, который будет автоматически масштабировать и обрезать изображения.
Зачем это нужно?
Допустим, у вас есть 100 изображений, которые нужно уменьшить до 300 пикселей в ширину. Или сжать до размеров аватара (100 на 100, например) и урезать до квадрата. Или уменьшить вдвое. Или произвести любую другую манипуляцию с масштабом и обрезкой...
Можете сразу скачать исходники:

Скачать resize_crop.zip

Функция масштабирования

Первой мы рассмотрим функцию масштабирования.
Код целиком:

function resize($file_input, $file_output, $w_o, $h_o, $percent = false) {     list($w_i, $h_i, $type) = getimagesize($file_input);     if (!$w_i || !$h_i) {         echo 'Невозможно получить длину и ширину изображения';         return;        }        $types = array('','gif','jpeg','png');        $ext = $types[$type];        if ($ext) {                $func = 'imagecreatefrom'.$ext;                $img = $func($file_input);        } else {                echo 'Некорректный формат файла';         return;        }     if ($percent) {         $w_o *= $w_i / 100;         $h_o *= $h_i / 100;     }     if (!$h_o) $h_o = $w_o/($w_i/$h_i);     if (!$w_o) $w_o = $h_o/($h_i/$w_i);      $img_o = imagecreatetruecolor($w_o, $h_o);     imagecopyresampled($img_o, $img, 0, 0, 0, 0, $w_o, $h_o, $w_i, $h_i);     if ($type == 2) {         return imagejpeg($img_o,$file_output,100);     } else {         $func = 'image'.$ext;         return $func($img_o,$file_output);     } } ?> 

Теперь разберём функцию по частям.
Вызов функции:

resize($file_input, $file_output, $w_o, $h_o, $percent = false); 

где $file_input – исходный файл, $file_output – файл, в который мы будем сохранять готовое изображение, $w_o и $h_o – ширина и высота объекта соответственно,$percent – логическое выражение, определяющее, в чем измеряется длина – в пикселях (по умолчанию) или в процентах.

Получаем ширину, высоту и тип исходного изображения.
Если у нас это не получается, выводим сообщение об ошибке и выходим из функции.

list($w_i, $h_i, $type) = getimagesize($file_input); if (!$w_i || !$h_i) {    echo 'Невозможно получить длину и ширину изображения';    return; } 

Тип мы получаем в формате числа: 1 – gif, 2 – jpeg, 3 – png.
Нам же нужно представить его в виде строки.
Если тип файла подходит, то запускаем функцию под названием imagecreatefrom + разрешение файла (например, imagecreatefromjpeg) с параметром исходного файла, если же нет – опять выводим ошибку.

$types = array('','gif','jpeg','png'); $ext = $types[$type]; if ($ext) {    $func = 'imagecreatefrom'.$ext;    $img = $func($file_input); } else {    echo 'Некорректный формат файла';    return; } 

Теперь переходим к размерам будущего файла.
Переводим проценты в пиксели и определяем размер недостающей стороны (если необходимо).

if ($percent) {     $w_o *= $w_i / 100;     $h_o *= $h_i / 100; } if (!$h_o) $h_o = $w_o/($w_i/$h_i); if (!$w_o) $w_o = $h_o/($h_i/$w_i); 

Создаём новое изображение и вставляем в него уменьшенный исходный файл.
Сохраняем во внешний файл.
Если сохраняем в jpeg, то дополнительно к первым двум параметрам указываем качество – число от 0 до 100, где 100 - максимально возможное качество.
Функция возвращает true, если запись в файл была выполнена успешно и false, если что-то пошло не так.

$img_o = imagecreatetruecolor($w_o, $h_o); imagecopyresampled($img_o, $img, 0, 0, 0, 0, $w_o, $h_o, $w_i, $h_i); if ($type == 2) {     return imagejpeg($img_o,$file_output,100); } else {     $func = 'image'.$ext;     return $func($img_o,$file_output); }  

Функция обрезки

Теперь функция обрезки.

function crop($file_input, $file_output, $crop = 'square',$percent = false) {     list($w_i, $h_i, $type) = getimagesize($file_input);     if (!$w_i || !$h_i) {         echo 'Невозможно получить длину и ширину изображения';         return;        }        $types = array('','gif','jpeg','png');        $ext = $types[$type];        if ($ext) {                $func = 'imagecreatefrom'.$ext;                $img = $func($file_input);        } else {                echo 'Некорректный формат файла';         return;        }     if ($crop == 'square') {         $min = $w_i;         if ($w_i > $h_i) $min = $h_i;         $w_o = $h_o = $min;     } else {         list($x_o, $y_o, $w_o, $h_o) = $crop;         if ($percent) {             $w_o *= $w_i / 100;             $h_o *= $h_i / 100;             $x_o *= $w_i / 100;             $y_o *= $h_i / 100;         }                if ($w_o < 0) $w_o += $w_i;             $w_o -= $x_o;            if ($h_o < 0) $h_o += $h_i;         $h_o -= $y_o;     }     $img_o = imagecreatetruecolor($w_o, $h_o);     imagecopy($img_o, $img, 0, 0, $x_o, $y_o, $w_o, $h_o);     if ($type == 2) {         return imagejpeg($img_o,$file_output,100);     } else {         $func = 'image'.$ext;         return $func($img_o,$file_output);     } } ?> 

Рассмотрим вызов функции:

crop($file_input, $file_output, $crop = 'square',$percent = false); 

Параметры функции – исходный($file_input) и конечный($file_output) файл, переменная $crop, которая принимает координаты обрезки, а по умолчанию обрезает файл до квадрата, и, как и в первой функции, переменная $percent, которая принимает значение true или false.

Сначала пишем точно такой же код определения типа файла и его размеров, что и в первом случае. Надеюсь, объяснять его не потребуется.

list($w_i, $h_i, $type) = getimagesize($file_input); if (!$w_i || !$h_i) {     echo 'Невозможно получить длину и ширину изображения';     return; } $types = array('','gif','jpeg','png'); $ext = $types[$type]; if ($ext) {     $func = 'imagecreatefrom'.$ext;     $img = $func($file_input); } else {     echo 'Некорректный формат файла';     return; } 

Если координаты обрезки не заданы, то обрезаем изображение до формы квадрата. Как?
Очень просто: находим наименьшую сторону исходного изображения, и присваиваем её ширине и длине конечного изображения.

if ($crop == 'square') {     $min = $w_i;     if ($w_i > $h_i) $min = $h_i;     $w_o = $h_o = $min; } else {     /*...*/         } 

Если же координаты существуют, то переносим их из массива в переменную и переводим проценты в пиксели (опять же, если это необходимо).
Получаем длину и ширину обрезаемой поверхности.

list($x_o, $y_o, $w_o, $h_o) = $crop; if ($percent) {     $w_o *= $w_i / 100;     $h_o *= $h_i / 100;     $x_o *= $w_i / 100;     $y_o *= $h_i / 100; } if ($w_o < 0) $w_o += $w_i; $w_o -= $x_o; if ($h_o < 0) $h_o += $h_i; $h_o -= $y_o; 

Теперь создаём новый файл, копируем кусок изображения по координатам, которые только что получили, и сохраняем этот кусок в файл.

$img_o = imagecreatetruecolor($w_o, $h_o); imagecopy($img_o, $img, 0, 0, $x_o, $y_o, $w_o, $h_o); if ($type == 2) {     return imagejpeg($img_o,$file_output,100); } else {     $func = 'image'.$ext;     return $func($img_o,$file_output); } 

Вот и всё.

Чтобы не быть голословной, вот решение тех задач, которые я поставила в начале:

Уменьшаем 100 изображений до 300 px в ширину:

$files = array_slice(scandir('photos/'),2); // получаем файлы из директории foreach ($files as $file) {     resize($file, $file, 300, 0); // ширину не указываем – скрипт определит её сам } 

Уменьшение и обрезка аватара:

crop('big.jpg', 'crop.jpg'); resize('crop.jpg', 'avatar.jpg', 100, 100); 



Уменьшаем изображение вдвое:

resize('big.jpg', 'small.jpg', 50, 50, true); 



Плюс ещё парочка задач:
Обрезаем изображение на 10 пикселей с каждой стороны:

crop('big.jpg', 'frame.jpg', array(10, 10, -10, -10)); 



Делим изображение на 4 равные части:

crop('big.jpeg', '1.jpeg', array(0, 0, 50, 50),true); crop('big.jpeg', '2.jpeg', array(50, 0, 100, 50),true); crop('big.jpeg', '3.jpeg', array(0, 50, 50, 100),true); crop('big.jpeg', '4.jpeg', array(50, 50, 100, 100),true); 


Вот и всё.