Client-side HEIC Conversion: A WASM Deep Dive
The Tech Stack: WASM and Web Workers
The core challenge with HEIC is that it's a proprietary Apple container. To decode it in a browser without a backend, I used libheif-js, which brings the power of C++ decoding to the browser via WebAssembly (WASM).
The biggest "gotcha" when implementing WASM for image processing is the main thread. If you run a heavy decoding task on the main JS thread, the entire UI freezes, leading to a terrible user experience. To fix this, I offloaded the binary data to a Web Worker. This allows the decoding to happen in the background, keeping the interface responsive.
Handling the HEIC Container Logic
One technical detail many developers overlook is that a .heic file isn't just a single image; it's a container. It often stores multiple frames, including low-res thumbnails and burst shots. If you simply grab the first frame the decoder returns, you'll frequently end up with a blurry 256x256 thumbnail instead of the actual photo.
I had to implement a resolution-check loop inside the Web Worker to ensure the highest quality output. Here is the specific logic used to isolate the primary image:
// 'decodedFrames' is the array of images extracted by the WASM decoder
let primaryImage = decodedFrames[0];
let maxResolutionArea = primaryImage.get_width() * primaryImage.get_height();
// Iterate through the HEIC container to isolate the main, high-res photo
for (let i = 1; i < decodedFrames.length; i++) {
let currentArea = decodedFrames[i].get_width() * decodedFrames[i].get_height();
if (currentArea > maxResolutionArea) {
primaryImage = decodedFrames[i];
maxResolutionArea = currentArea;
}
}
// 'primaryImage' is now locked in. We draw it to an OffscreenCanvas
// and export it locally as a Blob.Practical Implementation Pipelines
Depending on the end-use case, I structured the processing into three distinct local pipelines to avoid unnecessary overhead:
- Web/CMS Pipeline: Optimized for JPG conversion. This is the go-to for assets that need to be uploaded to a website where compatibility is king.
- UI/UX Design Pipeline: Focused on PNG conversion. Since Figma and Photoshop require lossless assets or transparency, this pipeline avoids the compression artifacts found in JPGs.
- Document Archiving Pipeline: A specialized compiler that stitches multiple HEIC frames into a single PDF, which is ideal for scanned contracts or whiteboard notes.
Performance Benchmarks
By moving the processing to the client side, the performance gains are immediate. In my local tests:
- Network Latency: Reduced from ~2-5 seconds (upload/download) to 0ms.
- Privacy: 100% local. You can literally turn off your Wi-Fi after the page loads and the converter still works.
- Throughput: Processing a 5MB HEIC file takes roughly 150ms-300ms on a modern M-series chip, compared to the several seconds wasted on HTTP roundtrips.
For anyone looking to implement this, I recommend checking out the
libheif project. If you are building a similar AI workflow or asset pipeline, keep in mind that OffscreenCanvas is your best friend for rendering these WASM-decoded blobs without blocking the UI.For those who want to see it in action, I've hosted the tools at https://heictools.io.