Laravel's First-Party Image Processing: A Practical Guide to Illuminate\Image
Laravel #Laravel #Image Processing #Illuminate\Image #WebP #Intervention Image

Laravel's First-Party Image Processing: A Practical Guide to Illuminate\Image

3 min read Mohamed Said Mohamed Said

Laravel 13.20 Introduces First-Party Image Processing

Laravel 13.20 added native image processing through the new Illuminate\Image component (PR #59276). Before this release, every resize or WebP conversion required wiring up a third-party package manually. Now the framework ships a fluent, immutable API that handles resizing, cropping, format conversion, quality control, effects, and storing results on any filesystem disk.

Setup

The GD and Imagick drivers are backed by Intervention Image v4, which is a suggested dependency. Install it with:

composer require intervention/image:^4.0

Laravel defaults to the GD driver. Switch to Imagick per-image or globally via the images.default config:

$image->usingImagick()->toBytes();

Creating an Image Instance

The new Request::image() method is the most convenient entry point for uploads:

$image = $request->image('avatar'); // ?Illuminate\Image\Image

For every other source, use the Image facade or Storage:

$image = Image::fromPath('/path/to/photo.jpg');
$image = Image::fromUrl('https://example.com/photo.jpg');
$image = Image::fromStorage('uploads/photo.jpg', 's3');
$image = Storage::disk('s3')->image('uploads/photo.jpg');

How the Pipeline Works

Every transformation returns a new Image instance and nothing is processed until you request output (store(), toBytes(), width(), etc.). This lets you branch a single base image into multiple variants without side effects:

$photo = Image::fromStorage('uploads/photo.jpg')->orient();

$thumbnail = $photo->cover(300, 300)->quality(60)->toWebp();
$display   = $photo->scale(width: 1600)->quality(80)->toWebp();

$thumbnail->storeAs('photos', 'photo-thumb.webp', disk: 's3');
$display->storeAs('photos', 'photo-display.webp', disk: 's3');

Calling orient() first auto-rotates the image using EXIF data—essential for phone camera uploads.

Resizing Methods

| Method | Behaviour | |---|---| | cover($w, $h) | Resize and crop to exact dimensions | | contain($w, $h, $bg) | Fit inside dimensions, pad with background | | scale($w, $h) | Proportional resize, never upscales | | resize($w, $h) | Force exact dimensions, may distort | | crop($w, $h, $x, $y) | Cut a region at the given offset |

Formats, Quality, and optimize()

Convert to any common format with dedicated methods:

$image->toWebp()->quality(80);
$image->toAvif()->quality(70);
$image->toPng();

The optimize() shortcut converts to WebP at quality 70 by default:

$image->optimize();           // WebP @ 70
$image->optimize('avif', 60); // AVIF @ 60

Storing Results

$path = $image->store('avatars');                     // hashed filename
$path = $image->storeAs('avatars', 'user-1.webp');    // explicit name
$path = $image->storePublicly('avatars', disk: 's3'); // public visibility

The hashed filename automatically uses the correct extension for the output format.

Practical Example: Avatar Upload Controller

public function update(Request $request)
{
    $request->validate(['avatar' => ['required', 'image', 'max:5120']]);

    $path = $request->image('avatar')
        ->orient()
        ->cover(512, 512)
        ->optimize()
        ->storePublicly('avatars', disk: 's3');

    $request->user()->update(['avatar_path' => $path]);

    return back();
}

Conditional Transformations

Image uses Laravel's Conditionable trait, so when() works as expected:

$image = $request->image('photo')
    ->when($request->boolean('grayscale'), fn ($img) => $img->grayscale())
    ->scale(width: 1200)
    ->optimize();

Key Takeaways

  • No extra wiring: Illuminate\Image is built into Laravel 13.20; just install Intervention Image v4.
  • Immutable pipeline: transformations return new instances, making multi-variant generation safe and clean.
  • scale() never upscales: safe default for responsive image generation.
  • optimize() is a one-call shortcut to WebP at quality 70.
  • Images cannot be serialized to queued jobs—store first, pass the path.
  • ImageException is the single exception type for all processing failures.

Source: A Practical Guide to Laravel's First-Party Image Processing — Laravel News

Found this useful?

Frequently Asked Questions

3 questions
Q01 Do I need to install a separate package to use Laravel's image processing in 13.20?
Yes, one package is required. The `Illuminate\Image` component is built into Laravel 13.20, but it relies on Intervention Image v4 as a suggested dependency. Run `composer require intervention/image:^4.0` to enable the GD or Imagick driver.
Q02 Can I send an Image instance to a Laravel queued job?
No. Attempting to serialize an `Image` instance for a queued job throws an `ImageException`. The recommended pattern is to store the image first and pass the resulting file path to the job instead.
Q03 What is the difference between scale() and resize() in Illuminate\Image?
`scale()` resizes proportionally and never upscales the image—it maps to Intervention's `scaleDown()` internally. `resize()` forces exact dimensions and may distort the image if the aspect ratio differs.

Continue reading

More Articles

View all