Как создать скрипт для автоматического ресайза изображений на PHP
Автоматическое изменение размера изображений на PHP помогает подготовить фотографии для сайта, интернет-магазина или галереи без ручной обработки каждого файла. Скрипт может принимать исходную картинку, уменьшать её до заданной ширины, сохранять пропорции и записывать готовый результат в отдельную папку.
Для решения задачи обычно используют встроенную библиотеку GD или расширение Imagick. GD доступна на большинстве хостингов и подходит для стандартных операций: ресайза, обрезки, конвертации JPEG, PNG и WebP. Imagick предлагает больше возможностей, особенно при работе с цветом, качеством и большими файлами.
Подготовка PHP-среды и файлов
Перед началом работы нужно проверить, подключено ли расширение GD. Временно создайте файл info.php с таким содержимым:
<?php
phpinfo();
Откройте его в браузере и найдите раздел GD. Если он отсутствует, активируйте расширение в настройках PHP или обратитесь к панели управления хостингом. На локальном сервере Windows нужная строка обычно находится в файле php.ini и выглядит как extension=gd.
Скрипт должен знать, где лежит исходное изображение и куда сохранить копию. Лучше не перезаписывать оригинал: исходник может понадобиться для повторной обработки с другим размером или качеством. Для безопасности также стоит разрешать только известные форматы и проверять реальный MIME-тип файла, а не доверять его расширению.
В простом сценарии можно обрабатывать изображения из папки uploads, а уменьшенные версии хранить в uploads/resized. Если каталог назначения ещё не существует, PHP создаст его с помощью mkdir(). Права на запись должны быть настроены так, чтобы веб-сервер мог создавать файлы, но посторонние пользователи не получили доступ к загрузке исполняемых скриптов.
Расчёт новых пропорций изображения
Ресайз изображения начинается с определения его исходной ширины и высоты. Для этого применяется функция getimagesize(). Если известна максимальная ширина, новая высота рассчитывается по формуле: исходная высота умножается на новую ширину и делится на исходную ширину.
Например, фотография размером 4000×3000 пикселей при ограничении ширины 1200 пикселей станет изображением 1200×900. Пропорции сохранятся, а картинка не будет растянута по вертикали. Если исходное изображение уже меньше заданного размера, его обычно не увеличивают, чтобы не ухудшать резкость.
$size = getimagesize($source);
$sourceWidth = $size[0];
$sourceHeight = $size[1];
$maxWidth = 1200;
if ($sourceWidth > $maxWidth) {
$newWidth = $maxWidth;
$newHeight = (int) round($sourceHeight * $newWidth / $sourceWidth);
} else {
$newWidth = $sourceWidth;
$newHeight = $sourceHeight;
}
Для превью с фиксированными шириной и высотой понадобится дополнительная логика. Можно вписать фотографию в заданную область с сохранением пропорций или выполнить центральную обрезку. Первый вариант не обрезает содержимое, а второй создаёт одинаковые карточки для каталога. Практические детали создания миниатюр через GD разобраны в материале создание превью изображений.
Полный пример скрипта на GD
Ниже приведён универсальный вариант для JPEG, PNG и WebP. Он загружает исходный файл, создаёт пустое изображение нужного размера, переносит в него содержимое и сохраняет результат. Функция imagecopyresampled() выполняет качественное масштабирование с интерполяцией пикселей.
<?php
$source = __DIR__ . '/uploads/photo.jpg';
$destination = __DIR__ . '/uploads/resized/photo.webp';
$maxWidth = 1200;
if (!is_file($source)) {
exit('Исходный файл не найден');
}
$info = getimagesize($source);
if ($info === false) {
exit('Файл не является изображением');
}
$sourceWidth = $info[0];
$sourceHeight = $info[1];
$mime = $info['mime'];
if ($sourceWidth > $maxWidth) {
$newWidth = $maxWidth;
$newHeight = (int) round($sourceHeight * $newWidth / $sourceWidth);
} else {
$newWidth = $sourceWidth;
$newHeight = $sourceHeight;
}
switch ($mime) {
case 'image/jpeg':
$sourceImage = imagecreatefromjpeg($source);
break;
case 'image/png':
$sourceImage = imagecreatefrompng($source);
break;
case 'image/webp':
$sourceImage = imagecreatefromwebp($source);
break;
default:
exit('Формат не поддерживается');
}
$result = imagecreatetruecolor($newWidth, $newHeight);
imagealphablending($result, false);
imagesavealpha($result, true);
$transparent = imagecolorallocatealpha($result, 0, 0, 0, 127);
imagefill($result, 0, 0, $transparent);
imagecopyresampled(
$result,
$sourceImage,
0,
0,
0,
0,
$newWidth,
$newHeight,
$sourceWidth,
$sourceHeight
);
imagewebp($result, $destination, 82);
imagedestroy($sourceImage);
imagedestroy($result);
echo 'Изображение обработано';
Пример сохраняет результат в WebP, поскольку этот формат часто уменьшает размер файла при сопоставимом визуальном качестве. Для JPEG вместо imagewebp() используется imagejpeg($result, $destination, 82), а для PNG — imagepng(). У PNG параметр качества работает иначе: в нём используется уровень сжатия от 0 до 9.
Прозрачность особенно важна при обработке PNG. Вызовы imagealphablending() и imagesavealpha() помогают сохранить альфа-канал. Для фотографий с JPEG они не обязательны. После завершения работы изображения нужно удалить из памяти функцией imagedestroy(), иначе при массовой обработке больших файлов процесс может завершиться из-за нехватки памяти.
Обработка загрузки и защита
Если файл поступает через HTML-форму, проверяйте ошибки загрузки, размер и тип. Ограничение размера защищает сервер от случайно отправленных многосотмегабайтных файлов. Проверка MIME через finfo_file() надёжнее, чем анализ имени вроде photo.jpg.
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['image']['tmp_name']);
finfo_close($finfo);
$allowed = [
'image/jpeg',
'image/png',
'image/webp'
];
if (!in_array($mime, $allowed, true)) {
exit('Недопустимый тип файла');
}
if ($_FILES['image']['size'] > 10 * 1024 * 1024) {
exit('Файл слишком большой');
}
Имя результата лучше генерировать самостоятельно: например, с помощью hash('sha256', uniqid('', true)). Это снижает риск перезаписи существующего файла и исключает опасные символы в имени. Каталог загрузок не должен позволять выполнять PHP-файлы. На сервере Apache для этого можно добавить правила, запрещающие выполнение скриптов в папке с пользовательскими файлами.
При пакетной обработке используйте список файлов из каталога и запускайте ресайз по одному. После каждого изображения освобождайте память. Если фотографии поступают из формы, полезно дополнительно создавать несколько вариантов: большую версию для страницы, среднюю для списка и маленькую миниатюру. Такой подход уменьшает время загрузки сайта и экономит мобильный трафик.
GD или Imagick для автоматического ресайза
GD хорошо подходит для небольшого сайта, стандартных фотографий и простого PHP-скрипта. Она легко вызывается без сложной конфигурации и содержит всё необходимое для изменения размеров, создания миниатюр и конвертации распространённых форматов. Ограничение GD проявляется при обработке очень больших файлов и сложных цветовых профилей.
Imagick является PHP-интерфейсом к ImageMagick. Его выбирают, когда требуется пакетная обработка, работа с TIFF, PDF, анимацией, профилями цвета или расширенными фильтрами. Однако расширение может быть недоступно на бюджетном хостинге, а неправильные настройки ImageMagick требуют отдельного внимания с точки зрения безопасности.
Для публикации изображений важен и сам контекст материала. Например, если сайт содержит визуальные карточки о повседневном уходе, можно заранее подготовить одинаковые превью для статьи материал об уходе за кожей. Скрипт при этом остаётся универсальным: ему неважно, изображена ли косметика, фотография товара или иллюстрация к записи.
| Критерий | GD | Imagick |
|---|---|---|
| Доступность на хостинге | Обычно высокая | Зависит от тарифа и настроек |
| Базовый ресайз | Подходит | Подходит |
| Поддержка сложных форматов | Ограниченная | Широкая |
| Потребление ресурсов | Умеренное | Может быть выше |
| Сложность настройки | Низкая | Средняя |
| Пакетная обработка | Возможна | Удобна для больших объёмов |
| Работа с цветом и профилями | Ограниченная | Расширенная |
Для WordPress такой обработчик можно подключить к событию загрузки изображения или запускать отдельной командой для уже существующих файлов. При большом количестве медиа лучше использовать очередь, чтобы не перегружать сервер во время одного веб-запроса. Перед публикацией проверьте размеры, качество, прозрачность и корректность имён файлов.
Сохраните исходники, настройте разрешённые форматы и протестируйте скрипт на портретных, альбомных и квадратных изображениях. После этого автоматический ресайз можно встроить в загрузку файлов, галерею или пакетную оптимизацию медиатеки, сократив объём изображений без ручной обработки.