Blog

HEIC support in the web workflow

HEIC is an efficient camera format and a surprisingly awkward browser input. Supporting it meant treating conversion as part of the workflow, not asking people to fix the file first.

An iPhone photo is not an edge case. Yet for a long time, dropping one straight into our web tools could produce the least useful sort of product message: unsupported file. The person had a normal photo. It was the browser workflow that had the unusual expectation.

Studio and Playground now accept HEIC and HEIF alongside JPEG, PNG, and WebP. File selection was the easy part. The preview, canvas checks, and upload path still needed pixels that browsers could decode consistently, so we built one shared conversion path around a browser-compatible working copy.

01 / A COMMON FILE, UNEVEN SUPPORT

“Open it in Photos and export a JPEG” is not a workflow

HEIC is common precisely because people do not think about it. A phone captures an image, stores it efficiently, and shares the file. The format only becomes visible when the next tool refuses it. Asking someone to convert the file elsewhere solves the decoder problem by turning it into their problem.

For a browser product, accepting the extension is not enough. We need a preview, decoded dimensions for safety checks, and a request body the processing path can handle predictably. Browser and canvas support for HEIC is not consistent enough to assume all three.

The goal was intentionally unremarkable

Pick a phone photo, see it in Studio, process it, and download the result. No detour through another app and no format lesson before the useful work starts.

02 / CONVERSION

One JPEG working copy, made only when needed

When Studio receives a HEIC or HEIF file, it loads heic2any on demand and converts the image to JPEG at 0.95 quality. The lazy import matters: someone uploading a PNG should not pay the download and initialization cost of a decoder they never use.

The browser-side lifecycle

Original HEICKept untouched on the user's device.
Working JPEGCreated once with the original base filename.
Preview + checksThe same decoded file feeds the visible preview and dimensions.
API requestThe working file is sent as image_file.

Studio uses that same JPEG for preview, dimension validation, and the multipart API request. Playground caches it for the selected upload, so changing output settings does not decode the HEIC source again and again. This sounds like a small optimization; on a large phone photo it is the difference between a control feeling immediate and feeling vaguely stuck.

03 / GUARDRAILS

Conversion does not skip the usual checks

The browser rejects empty files, files above the shared upload limit, and MIME types outside the supported set. After conversion, Studio decodes the working image and checks that each dimension falls between 50 and 20,000 pixels. The production orchestrator also registers its HEIC and HEIF decoder for direct API inputs.

Before conversion

Check source type, empty files, and the public transfer-size boundary.

After conversion

Decode the working copy and verify its actual pixel dimensions.

At processing

Let the API perform its own byte, pixel, and image-decode validation.

On failure

Offer JPEG, PNG, and WebP as practical fallback formats.

A conversion can still fail. The source may be damaged, use a variation the decoder cannot read, or run into a browser resource limit. In that case the error says what happened and names fallback formats. It does not pretend every file carrying an HEIC extension contains decodable image data.

04 / SOURCE FIDELITY

The working copy is useful, and it is still a copy

HEIC-to-JPEG conversion is lossy. A 0.95 quality setting is intentionally high, but it does not preserve the exact camera file or all of its metadata. That tradeoff buys a broadly compatible preview and upload path; it should not be confused with archival preservation.

Preserve the source that matters. Process the derivative that works.

Applications that need the original for metadata, later edits, or compliance should save it before processing. The BackgroundErase request can use a compatible derivative while the original remains in the application's storage. The returned cutout is another derived asset, not a replacement for the camera source.

That separation made the feature easier to reason about. Studio needs a dependable working image. A customer archive may need the untouched original. Those are two jobs, and forcing one file to serve both tends to make each job worse.

HEIC and HEIF now follow the same visible upload flow as the browser-native formats.

Try a phone photo in Studio