Intervention Image is the most popular PHP library for image processing, and version 4 works with Laravel 13. You create an ImageManager with a driver (GD, Imagick or libvips), decode an image, chain methods such as scale(), cover() or blur(), and save or encode the result. This tutorial gives you the core workflow and explains which resize method fits which job.
Targets: Laravel 13 (PHP 8.3 to 8.5) and intervention/image 4, which requires PHP 8.3 or newer, the Mbstring extension and one image extension.
Step 1: Install the package
composer require intervention/imageCheck that GD or Imagick is loaded with php -m. GD is part of most PHP installs. Imagick is faster for large images. Support for libvips is available through an add-on driver package.
Step 2: Create the manager and decode an image
use Intervention\Image\Drivers\Gd\Driver;
use Intervention\Image\ImageManager;
$manager = ImageManager::usingDriver(Driver::class);
$image = $manager->decode(storage_path('app/public/photos/original.jpg'));
$image->width(); // for example 4000
$image->height(); // for example 3000Version 4 uses ImageManager::usingDriver() and decode(). Older tutorials that use new ImageManager(new Driver()) and read() describe version 3.
Switch drivers by changing one import, for example Intervention\Image\Drivers\Imagick\Driver.
Which resize method should I use?
These are the most useful ones from the resizing documentation:
resize($width, $height)sets exact dimensions and may distort the picture if the ratio differs.scale(width: 800)resizes proportionally. Give only one side and the other is calculated.scaleDown(width: 800)does the same but never enlarges the image.cover(400, 400)crops and resizes to fill the exact size, which is ideal for square thumbnails or avatars.contain(400, 400)fits the whole image inside the size and fills the rest with a background color.crop($width, $height, $x, $y)cuts out a rectangle.
$image->scaleDown(width: 1200); // responsive image
$image->cover(400, 400); // square thumbnail
$image->contain(800, 450, 'ffffff'); // 16:9 canvas with white barsStep 3: Save or encode the result
Save directly. The file extension of the path selects the format, and extra named arguments set encoder options:
$image->save(storage_path('app/public/photos/thumb.webp'), quality: 80);Or encode first when you want to return or store the data yourself:
use Intervention\Image\Format;
$encoded = $image->encodeUsingFormat(Format::WEBP, quality: 80);
Storage::disk('public')->put('photos/thumb.webp', (string) $encoded);The encoded object can be cast to a string, saved with save($path), turned into a data URI with toDataUri() or read as a stream.
Step 4: Chain methods in a real service
<?php
namespace App\Services;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Drivers\Gd\Driver;
use Intervention\Image\Format;
use Intervention\Image\ImageManager;
class AvatarService
{
public function make(string $sourcePath, string $name): string
{
$encoded = ImageManager::usingDriver(Driver::class)
->decode($sourcePath)
->cover(300, 300)
->encodeUsingFormat(Format::WEBP, quality: 80);
$path = 'avatars/'.$name.'.webp';
Storage::disk('public')->put($path, (string) $encoded);
return $path;
}
}The service takes a source file, makes a square 300 pixel avatar, converts it to WebP and stores it on the public disk. It returns the relative path to save in the database.
Step 5: Add effects when you need them
Intervention includes effects such as blur(5), sharpen(10) and more in the effects documentation. They take a numeric level and are chained like any other method. The documentation notes that blur with the GD driver can be slow at high levels, so limit it.
Should I use the Laravel integration package?
The intervention/image-laravel package adds a facade and a published config file so the driver is set in one place. It is optional. The service-based approach above has no extra setup and is easy to test.
How do I check that it works?
- Run the service from Tinker with a real file path and a name.
- Open the saved file and confirm it is 300 by 300 pixels.
- Try a very wide image and confirm that
cover()crops the center instead of stretching.
Common mistakes
- Following version 3 examples: names and constructors differ in version 4.
- Using resize() for photos: it can distort. Use
scale()orcover(). - Missing extension: install GD or Imagick, otherwise decoding fails.
- Saving into a missing folder: create it first.
- Processing huge images in the request: queue the job for many or large files.
FAQ
Which driver should I pick?
Imagick for speed and format support, GD when Imagick is not available.
Can I process uploads without saving them first?
Yes. Use the uploaded file's real path with decode() and write the output wherever you need it.
Does Intervention Image 4 support Laravel 13?
The library is framework independent and requires PHP 8.3 or newer, which Laravel 13 also requires. Check the package's changelog for any Laravel-specific notes when you upgrade.



