a photo of a meerkat and some rocks, with a diagonal split in the middle where the top left part of the image looks bright and the bottom right looks dull

Batch scaling HEIC images while preserving HDR on macOS

My automated photo compression workflow broke because when automating picture compression in macOS, it somehow, seemingly randomly discarded the HDR information. Gasp! I had to investigate.

Let’s start from the beginning.

Now that both my Apple iPhone and my Hasselblad camera can take HEICs in HDR (high-dynamic range, essentially images with extra brightness that can adapt to your display), I noticed HDR breaks my workflow.

Here’s a sample image with HDR. WordPress currently doesn’t support this, so I had to directly embed the image. (Looks like WordPress 7.1 is going to address this with client-side transcoding!) If you have a supported OS, browser and display, the background of this glass is very bright. If not, it’ll just show in SDR.

an image of a transparent glass with some berries floating in liquid, with a bright blurry window in the background

I’d usually import images from both devices, then import compressed versions of those into my Apple Photos library that I then sync back to my phone. The high-res versions and RAWs would go on my NAS and, if they’re great photos that I’d like to edit, also a secondary backup. I do this because I have hundreds of gigabytes of photos and Apple Photos doesn’t support distributed libraries (like for example Final Cut Pro does).

a chart of my convoluted photo editing workflow, involving my phone and camera, Mac, NAS and another form off backup, with photos going from my phone to the Mac where I'll weed and edit them and then moving some of them back to my phone, while keeping the high-res versions only on the NAS and some on the backup

As part of this workflow, I used to scale down images, using Automator actions. I realized, however, that doing so sometimes removed the HDR. But other times, it’s just fine.

So I investigated. It turned out that the issue was only with HDR HEICs from my iPhone. Images created in Pixelmator Pro or directly with my Hasselblad Camera didn’t have that issue.

So how are Apple HEICs different from Hasselblad HEICs?

It turns out that instead of just encoding HDR using the color space and extended dynamic range of the image itself, Apple uses gain maps that are attached to the image like a secondary image in the same container/file.

Greg Benz explains that here nicely and there’s also a nice overview page here. A gain map essentially another image that is encoded with the main image, containing additional brightness information. The computer displaying the image will then use the main image and apply the second image to that, using a transfer function that depends the display capabilities. This ensures that, the brightness range of the image beyond “paper white” (the brightness/white point considered SDR) will be compressed into the capabilities of the display and excess brightness never “clips” and there’s isn’t a massive chunk that just ends up at maximum brightness.

When investigating, I was also able to confirm that my other image that I’ve been resizing, from my camera and exported out of Pixelmator pro, where not using these gain maps but instead just had a wider color space/dynamic range to begin with.

Sourcebit depth (per RGB channel)How does HDR Work?
iPhone 16 Pro8gain map
Pixelmator Pro HDR Export10HDR10/PQ
Hasselblad X2D II10extended range Display P3
Comparison of HDR storage methods.

Why is it like this?

Presumably, this is done to save space. Apple’s iPhone gain maps are only a quarter of the actual base image (half width, half height). They only need a single channel.

Processing this (and restoring the HDR) is fast, because all of this can be processed nicely using GPU compute. The smaller gain map can be used just like another channel, due to the GPU interpolating the gain map in hardware.

Why couldn’t I resize the iPhone images?

Well, it turns out, when resizing an image using e.g. Automator, the gain map is just discarded. Then resulting image is then just SDR. That was the issue, and that’s also why resizing other images (with “native” HDR) would work just fine.

This was on macOS 26.5.2.

How to fix it

The HDR resizing can be fixed by attaching an HDR gain map to the resized image.

Unfortunately, it looks like, both Automator and Shortcuts have the same issue: when resizing images, the gain map is discarded. And there doesn’t seem to be any setting that will prevent that from happening.

So I made a tool that re-encodes the image at target size while retaining the gain map.

At first, I resized the image and re-attached the gain map, but then realized I’d typically also want the gain map to be smaller. Otherwise I might run into a situation where the base image is larger than the gain map.

This means that I also needed to add the ability to resize the gain map. With these options I can now resize images while maintaining HDR.

The code of this exercise can be found here:

HDR editing is a bit inconsistent

While I was investigating I also noticed that die interoperability of the different HDR formats and tools is overall inconsistent.

  • When editing e.g. a 3FR RAW, (from the Hasselblad camera), it shows in HDR in Apple Photos, but exporting it from Apple Photos using the same settings I used for HEIC would discard the HDR information.
  • The same RAW edited in Pixelmator Pro, however, is also HDR and still HDR after importing into apple Photos via HEIC.
  • Opening an iPhone HDR HEIC in Pixelmator Pro, makes it HDR, even if “Open HDR Content” is disabled.
  • However, opening a Hasselblad-created HDR HEIC in Pixelmator Pro is SDR, unless “Open HDR Content” is checked.

Overall, I hope that automated image resizing like this will be easier in the future.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *