Validate and Convert HEIC Images in Laravel 13.24
Laravel PHP #Laravel #HEIC #Image Processing #Imagick #AVIF #WebP

Validate and Convert HEIC Images in Laravel 13.24

4 min read Mohamed Said Mohamed Said

HEIC Image Support Lands in Laravel 13.24

Every iPhone sold in the last several years captures photos in HEIC by default — a format roughly half the size of an equivalent JPEG. The catch: Chrome and Firefox cannot render it. Until Laravel 13.24, HEIC files were rejected before they even reached the image driver. That changes now.

Laravel 13.24 extends the image validation rule to accept heic, heif, and avif, adds a toHeic() output method, and wires everything through the existing image API.

Server Requirements

PHP cannot decode HEIC on its own. You need the Imagick extension with ImageMagick's HEIF delegate compiled in (built on libheif). The GD driver cannot read HEIC at all.

Verify your delegate is present before deploying:

php -r "print_r(Imagick::queryFormats('HEI*'));"

An empty array means the delegate is missing. On Debian/Ubuntu install libheif1; on macOS the Homebrew imagemagick formula includes it. AVIF is more forgiving — GD can decode it when PHP was built against libavif.

Install Intervention Image if you have not already:

composer require intervention/image:^4.0

Validating HEIC Uploads

The image rule now recognises heic, heif, and avif with no extra configuration:

$request->validate([
    'photo' => ['required', 'image', 'max:12288'],
]);

To be explicit about accepted formats, use the mimes rule:

'photo' => ['required', 'mimes:jpg,png,webp,heic', 'max:12288'],

Both rules resolve the type from file contents rather than trusting the browser-supplied MIME type, so image/heic and image/heif variants are handled consistently.

Converting on Upload

Storing a HEIC file as-is means broken images for most visitors. Convert during the upload request:

$path = $request->image('photo')
    ->usingImagick()
    ->orient()
    ->scale(width: 2000)
    ->toWebp()
    ->quality(80)
    ->store('photos');

Two details matter here:

  • usingImagick() is required — the default GD driver cannot read HEIC.
  • orient() reads EXIF rotation metadata and corrects it, which is critical for portrait phone shots stored as landscape frames with a rotation flag.

The stored filename gets the correct extension automatically: a HEIC input converted to WebP is saved as photos/{hash}.webp.

Serving AVIF With a WebP Fallback

AVIF is typically 20–30% smaller than WebP at comparable quality. Generate both variants from one source and let the browser choose:

$source = $request->image('photo')->usingImagick()->orient()->scale(width: 2000);

$avif = $source->toAvif()->quality(70)->storeAs('photos', "{$id}.avif");
$webp = $source->toWebp()->quality(80)->storeAs('photos', "{$id}.webp");
<picture>
    <source srcset="{{ Storage::url("photos/{$photo->id}.avif") }}" type="image/avif">
    <img src="{{ Storage::url("photos/{$photo->id}.webp") }}" alt="{{ $photo->caption }}">
</picture>

AVIF encoding is slower than WebP, so if uploads are synchronous this is a good candidate for a queued job.

Writing HEIC Output

Output to HEIC is also supported via toHeic():

Image::fromPath(storage_path('app/photo.jpg'))
    ->usingImagick()
    ->toHeic()
    ->quality(80)
    ->store('photos');

The heif alias is normalised to heic throughout — optimize('heif') produces the same output, files are stored with the .heic extension, and mimeType() reports image/heic.

Error Handling

If a file reaches the driver in an unsupported format, an ImageException is thrown:

The image format [image/tiff] is not supported.

This same exception surfaces when a HEIC file hits an Imagick build without the HEIF delegate — a deployment issue, not a user error. Validate the delegate on the server as part of your release checklist.

Key Takeaways

  • Laravel 13.24 adds heic, heif, and avif to the image validation rule — no configuration needed.
  • HEIC decoding requires Imagick with the HEIF delegate; GD cannot handle it.
  • Always call usingImagick() and orient() when processing phone photos.
  • Generate AVIF + WebP variants and use <picture> for optimal browser delivery.
  • toHeic() enables HEIC output for Apple-device pipelines and archives.
  • A missing HEIF delegate throws ImageException — check it at deploy time.

Source: Validate and Convert HEIC Images in Laravel — Laravel News

Found this useful?

Frequently Asked Questions

3 questions
Q01 Why does HEIC validation fail even after upgrading to Laravel 13.24?
The most common cause is a missing HEIF delegate in your ImageMagick build. Run `php -r "print_r(Imagick::queryFormats('HEI*'));"` on your server. An empty array means the delegate is not compiled in. On Debian/Ubuntu, install `libheif1`; on macOS, reinstall ImageMagick via Homebrew. The GD driver cannot read HEIC regardless of Laravel version.
Q02 Do I need to call usingImagick() explicitly when processing HEIC uploads?
Yes. Laravel's image API defaults to the GD driver, which cannot decode HEIC files. You must chain `->usingImagick()` before any transformation on a HEIC input, otherwise the operation will fail.
Q03 What is the difference between using the image rule and the mimes rule for HEIC uploads?
Both rules resolve the file type from its contents rather than the browser-supplied MIME type, so both handle the `image/heic` and `image/heif` variants correctly. The `image` rule is the simpler option and now includes HEIC, HEIF, and AVIF automatically. The `mimes` rule is useful when you want to explicitly whitelist a specific set of formats.

Continue reading

More Articles

View all