Работа с изображениями
На этой странице
Введение
Laravel предоставляет выразительный API для работы с изображениями, который позволяет изменять размер, обрезать, кодировать и сохранять изображения, используя те же удобные соглашения, что и во всем фреймворке. Возможности Laravel для работы с изображениями основаны на Intervention Image и поддерживают PHP-расширения GD и Imagick.
API изображений полезен при работе с загруженными файлами, файлами, сохраненными на дисках файловой системы Laravel, локальными файлами, удаленными URL или необработанными байтами изображения:
use Illuminate\Support\Facades\Image;
$path = Image::fromStorage('avatars/photo.jpg', 'public')
->cover(400, 400)
->toWebp()
->quality(80)
->storePublicly('avatars', 'public');
Работа с изображениями может активно использовать CPU и память. Для обработки больших изображений рассмотрите выполнение работы в задании очереди, а не во время HTTP-запроса, который принимает загрузку.
Установка
Перед использованием возможностей Laravel для работы с изображениями установите пакет Intervention Image через Composer:
composer require intervention/image:^4.0
Также убедитесь, что в вашей установке PHP установлено расширение GD или Imagick, в зависимости от того, какой драйвер будет использовать приложение.
Конфигурирование
Файл конфигурации изображений Laravel находится по адресу config/image.php. Если в вашем приложении нет файла конфигурации image, вы можете опубликовать его с помощью Artisan-команды config:publish:
php artisan config:publish image
Файл конфигурации изображений позволяет указать драйвер изображений по умолчанию для приложения. Также драйвер по умолчанию можно указать с помощью переменной окружения IMAGE_DRIVER. Поддерживаемые драйверы: gd и imagick:
IMAGE_DRIVER=imagick
Чтение изображений
Фасад Image предоставляет несколько методов для чтения изображений из распространенных источников. Содержимое изображения загружается лениво, поэтому источник обычно не читается до обработки изображения или запроса его байтов.
Загруженные файлы
Вы можете получить загруженное изображение из входящего запроса с помощью метода image. Этот метод возвращает экземпляр Illuminate\Image\Image для загруженного файла или null, если файл отсутствует:
use Illuminate\Http\Request;
Route::post('/avatar', function (Request $request) {
$request->validate(['avatar' => ['required', 'image']]);
$path = $request->image('avatar')
->cover(400, 400)
->toWebp()
->storePublicly('avatars', 'public');
// ...
});
Альтернативно, вы можете создать экземпляр изображения из экземпляра Illuminate\Http\UploadedFile с помощью метода fromUpload:
use Illuminate\Support\Facades\Image;
$image = Image::fromUpload($request->file('avatar'));
Когда изображение создано из загруженного файла, базовый загруженный файл можно получить с помощью метода file:
$file = $image->file();
Файлы из хранилища
Вы можете создать экземпляр изображения из файла, сохраненного на одном из дисков файловой системы приложения, с помощью метода fromStorage. Первый аргумент – путь к файлу, второй аргумент – имя диска:
use Illuminate\Support\Facades\Image;
$image = Image::fromStorage('avatars/photo.jpg', disk: 'public');
Также можно создавать экземпляры изображений напрямую из экземпляра диска файловой системы с помощью метода image:
use Illuminate\Support\Facades\Storage;
$image = Storage::disk('public')->image('avatars/photo.jpg');
Другие источники
Фасад Image также содержит методы для создания экземпляров изображений из необработанных байтов, локальных путей к файлам, удаленных URL и строк, закодированных в Base64:
use Illuminate\Support\Facades\Image;
$image = Image::fromBytes($contents);
$image = Image::fromBase64($base64);
$image = Image::fromPath(storage_path('app/avatars/photo.jpg'));
$image = Image::fromUrl('https://example.com/photo.jpg');
Изменение изображений
Экземпляры изображений неизменяемы. Каждый метод изменения возвращает новый экземпляр изображения с добавленным преобразованием в конвейер обработки, что позволяет свободно выстраивать цепочки методов:
$image = $request->image('avatar')
->orient()
->cover(400, 400)
->sharpen(10);
Преобразования выполняются в порядке их добавления в конвейер изображения, а кодирование изображения выполняется только один раз в конце.
Изменение размера изображений
Метод resize изменяет размер изображения до указанных размеров. Вы можете передать ширину и высоту или только одно измерение с помощью именованных аргументов:
$image = $image->resize(800, 600);
$image = $image->resize(width: 800);
$image = $image->resize(height: 600);
Метод scale пропорционально уменьшает изображение так, чтобы оно поместилось в указанные размеры. Этот метод никогда не увеличивает размер изображения:
$image = $image->scale(800, 600);
$image = $image->scale(width: 800);
$image = $image->scale(height: 600);
Метод cover изменяет размер и обрезает изображение так, чтобы оно полностью покрывало указанные размеры:
$image = $image->cover(400, 400);
Метод contain изменяет размер изображения так, чтобы оно поместилось в указанные размеры с сохранением всего изображения. При необходимости пустое пространство будет заполнено необязательным фоновым цветом:
$image = $image->contain(400, 400);
$image = $image->contain(400, 400, '#ffffff');
Вы можете обрезать изображение с помощью метода crop. Первые два аргумента – желаемые ширина и высота, а необязательные третий и четвертый аргументы задают координаты x и y для обрезки:
$image = $image->crop(300, 200);
$image = $image->crop(300, 200, x: 50, y: 25);
Другие преобразования
Laravel также предоставляет множество дополнительных методов преобразования изображений:
$image = $image->orient();
$image = $image->rotate(90);
$image = $image->rotate(90, '#ffffff');
$image = $image->blur(5);
$image = $image->grayscale();
$image = $image->sharpen(10);
$image = $image->flipVertically();
$image = $image->flipHorizontally();
Метод orient поворачивает изображение согласно данным ориентации EXIF. Метод rotate поворачивает изображение по часовой стрелке на указанный угол и принимает необязательный фоновый цвет. Методы blur и sharpen принимают значения от 0 до 100.
Условные преобразования
Экземпляры изображений поддерживают трейт Laravel Conditionable, что позволяет условно применять преобразования с помощью методов when и unless:
$image = $request->image('avatar')
->when($request->boolean('crop'), fn ($image) => $image->cover(400, 400))
->unless($request->boolean('preserve_format'), fn ($image) => $image->toWebp());
Кодирование изображений
По умолчанию обработанные изображения кодируются в исходном формате. Однако перед получением или сохранением изображения вы можете преобразовать его в другой поддерживаемый формат:
$image = $image->toWebp();
$image = $image->toJpg();
$image = $image->toJpeg();
Метод quality позволяет задать качество вывода. Значение качества будет ограничено диапазоном от 1 до 100:
$image = $image->toWebp()->quality(80);
Метод optimize – удобное сокращение для преобразования изображения в указанный формат и установки его качества. По умолчанию изображения оптимизируются как WebP с качеством 70:
$image = $image->optimize();
$image = $image->optimize(format: 'jpg', quality: 85);
Вы можете получить содержимое обработанного изображения как строку байтов, строку в Base64 или data URI:
$bytes = $image->toBytes();
$base64 = $image->toBase64();
$dataUri = $image->toDataUri();
Экземпляр изображения также можно привести к строке, чтобы получить его обработанные байты:
$bytes = (string) $image;
Сохранение изображений
Метод store сохраняет обработанное изображение на одном из дисков файловой системы вашего приложения. Как и для загруженных файлов, Laravel сгенерирует уникальное имя файла и вернет сохраненный путь. Второй аргумент можно использовать для указания диска:
$path = $request->image('avatar')
->cover(400, 400)
->store(path: 'avatars');
$path = $request->image('avatar')
->cover(400, 400)
->store(path: 'avatars', disk: 's3');
Вы можете использовать метод storeAs, чтобы указать имя сохраняемого файла:
$path = $request->image('avatar')
->cover(400, 400)
->storeAs(path: 'avatars', name: 'avatar.jpg', disk: 'public');
Методы storePublicly и storePubliclyAs сохраняют изображение с видимостью public:
$path = $request->image('avatar')
->cover(400, 400)
->storePublicly(path: 'avatars', disk: 'public');
$path = $request->image('avatar')
->cover(400, 400)
->storePubliclyAs(path: 'avatars', name: 'avatar.webp', disk: 'public');
Если изображение не удалось сохранить, методы сохранения вернут false.
Получение сведений об изображениях
Вы можете получить MIME-тип, расширение, размеры, ширину и высоту изображения с помощью следующих методов:
$mimeType = $image->mimeType();
$extension = $image->extension();
[$width, $height] = $image->dimensions();
$width = $image->width();
$height = $image->height();
Эти методы работают с обработанным изображением. Например, вызов width после cover(400, 400) вернет 400.
Драйверы изображений
Пользовательские драйверы изображений
Менеджер изображений Laravel расширяет базовый класс Illuminate\Support\Manager Laravel. Это означает, что вы можете регистрировать пользовательские драйверы изображений с помощью метода extend, доступного в менеджере изображений и фасаде Image.
Пользовательские драйверы изображений должны реализовывать интерфейс Illuminate\Contracts\Image\Driver. Метод process получает исходное содержимое изображения и упорядоченный Illuminate\Image\ImagePipeline, который должен быть применен к изображению, и должен вернуть байты обработанного изображения:
<?php
namespace App\Images;
use Illuminate\Contracts\Image\Driver;
use Illuminate\Image\ImagePipeline;
class VipsDriver implements Driver
{
/**
* Process the given image contents with the specified pipeline.
*/
public function process(string $contents, ImagePipeline $pipeline): string
{
// Apply the pipeline's transformations and output options...
return $contents;
}
/**
* Register a transformation handler.
*/
public function transformUsing(string $transformation, callable $callback): static
{
// Store the handler so it may be applied while processing the pipeline...
return $this;
}
}
Чтобы лучше понять, как реализовать пользовательский драйвер изображений, вы можете изучить встроенный класс фреймворка
Illuminate\Image\Drivers\InterventionDriver.
После реализации пользовательского драйвера его можно зарегистрировать с помощью метода extend фасада Image. Обычно это следует делать в методе boot сервис-провайдера:
use App\Images\VipsDriver;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Image;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Image::extend('vips', function (Application $app) {
return new VipsDriver;
});
}
После регистрации драйвера вы можете использовать его для конкретного изображения с помощью метода using:
$image = $request->image('avatar')
->using('vips')
->cover(400, 400);
Также можно настроить пользовательский драйвер как драйвер изображений по умолчанию для приложения с помощью опции default в файле конфигурации config/image.php или переменной окружения IMAGE_DRIVER:
IMAGE_DRIVER=vips
Пользовательские преобразования
Приложения и пакеты могут определять пользовательские преобразования, создавая класс, который реализует контракт Illuminate\Contracts\Image\Transformation. Затем пользовательские преобразования можно добавить в конвейер изображения с помощью метода transform:
<?php
namespace App\Images\Transformations;
use Illuminate\Contracts\Image\Transformation;
class Pixelate implements Transformation
{
public function __construct(
public readonly int $size,
) {
//
}
}
Затем зарегистрируйте обработчик для преобразования и драйвера с помощью метода transformUsing фасада Image. Обычно это следует делать в методе boot сервис-провайдера:
use App\Images\Transformations\Pixelate;
use Illuminate\Support\Facades\Image;
use Intervention\Image\Interfaces\ImageInterface;
Image::transformUsing('gd', Pixelate::class, function (ImageInterface $image, Pixelate $transformation) {
return $image->pixelate($transformation->size);
});
После регистрации обработчика преобразования вы можете применить преобразование к изображению:
use App\Images\Transformations\Pixelate;
$image = $request->image('avatar')
->transform(new Pixelate(12))
->store('avatars');