как проще всего обрезать фото пропорционально к примеру 200px по ширине перед сохранением?Laravel
public function store(Request $request) {
$image = $request->file('image');
//перед сохранением изменить размер пропорционально к примеру если было загружено 2000 на 1000px то по ширине к примеру сделать 200p а высота пропорционально чтобы уменьшилась
if ($image) {
$path_image = $image->store('uploads', 'public');
}
}
спасибо!
Ответы (1 шт):
PHP не умеет изменять размер существующего изображения. Но он умеет копировать кусок изображения с последующим изменением размера. С помощью этого лайфхака можно реализовать функцию resize().
/**
* Resize of image
*
* @param int $desiredWidth Ширина, до которой нужно обрезать
* @param string $path Путь до файла, которое нужно обрезать
* @param string $destination Путь до файла, куда сохранить получившееся изображение
* @param int $quality Качество обрезанного изображения (в процентах)
*
* @return void
* @throws Exception
*/
public function resize(int $desiredWidth, string $path, string $destination, int $quality = 80)
{
$binary = file_get_contents($path);
$imageSize = !empty($binary) ? getimagesizefromstring($binary) : null;
// Проверяем, что файл не пустой
if (!$imageSize) {
throw new Exception("Файл пустой");
}
// Получаем размер файла
[0 => $width, 1 => $height] = $imageSize;
// Создаем "виртуальное" изображение в памяти
$sourceImage = imagecreatefromstring($binary);
// Если файл больше, чем нам нужно, то обрезаем
if ($desiredWidth < $width) {
// Высчитываем высоту по пропорции
$desiredHeight = floor($height * ($desiredWidth / $width));
// Результирующее "виртуальное" изображение в памяти, в которое будем копировать первоначальное изображение
$virtualImage = imagecreatetruecolor($desiredWidth, $desiredHeight);
// Копируем изначальное изображение в результирующее
imagecopyresampled($virtualImage, $sourceImage, 0, 0, 0, 0, $desiredWidth, $desiredHeight, $width, $height);
// Сохраняем результирующее изображение
imagejpeg($virtualImage, $destination, $quality);
} else if($path !== $destination) {
// Первоначальное изображение оказалось меньше, чем нам нужно
// Поэтому просто копируем файл
copy($path, $destination);
}
}
Для вашего примера, нужно использовать так:
public function store(Request $request) {
$image = $request->file('image');
// Сначала сохраняем файл, который прислал клиент
if ($image) {
$pathImage = $image->store('uploads', 'public');
// Точно не помню, что содержится в $pathImage.
// Если там абсолютный путь (/var/www/...), то используем переменную "как есть"
// Если же там относительный путь (public/...), то его нужно преобразовать в абсолютный:
// $pathPage = storage_path('app/' . $pathImage);
resize(200, $pathImage, $pathImage);
}
}
P.s. Также рекомендую использовать данную функцию при каждом сохранении изображения. Так как через изображение может быть совершена атака на ваш сервер (подробнее тут https://www.securitylab.ru/analytics/456285.php).
То есть идея в том, что если изменять размер не нужно, то в качестве $desiredWidth в resize() передаем реальный размер изображения.
При копировании куска изображения, PHP удаляет комментарии из изображения, тем самым блокирую возможность провести атаку