dcoles

Oddly Specific

Principal Software Engineer and Systems Architect at Sony Interactive Entertainment (PlayStation)šŸŽ®

ā•Œ

@fixingtheuniverse is my stash of unread papers and articles šŸ“‘

--

🦘 šŸŒ‡ šŸ³ļøā€šŸŒˆ

--

You are visitor number visit counter

posts from @dcoles tagged #hdr

also:

🚨 cohost's post editor not letting you upload images in your favourite obscure image format? No problem! Just embed the image in your SVG using the image tag with a data URL! #svg crimes

So here's the HDR version (AVIF is one of the few widely-supported image formats that can support HDR). Those bright spots are actually brighter than #ffffff!

It turned out that the easiest way to create one was using ffmpeg to convert it from linear OpenEXR:

ffmpeg -i ultra_hdr_image.exr \
    -vf "zscale=primariesin=bt709:matrixin=709:transferin=linear:primaries=bt709:matrix=790:transfer=arib-std-b67:npl=400" \
    -c:v libaom-av1 -still-picture 1 ultra_hdr_image.avif

Apologies if this post is a little incoherent. I finally got this to work, but it's now 1:40 am. Will grammar check in the morning. As in the part of the morning when I'm supposed to be awake. >.>;;;.

edit: Hopefully it's now a bit more grammatically correct.



Late last year Google introduced support for a feature called Ultra HDR that allows storing additional dynamic range information1 in a standard JPEG container. I only found out about it when I noticed the an "Ultra HDR" tag on a couple of my more recent photos when I was looking through them in Google Photos.

So great, new format. How do I get it into a format that anything outside of Android will recognise?

Google helpfully has provided a library called libultrahdr which can be used to encode and decode these special JPEGs, and even better, there's a demo command-line app for it2.

It supports a couple of output formats, but we're going to go with the simplest one which is UHDR_IMG_FMT_64bppRGBAHalfFloat with a linear transfer function. The nice thing about this is we can skip futzing around with non-linear transfer functions like Hybrid Log Gamma (HLG) and Perceptual Quantizer (PQ) (colourspace conversion is notoriously tricky to get right). The downside that is requires 64-bits (8 bytes) per pixel to store each sample as a half-precision float.

First lets convert the Ultra HDR JPEG to raw half-float samples:

# `-m 1` is decode
# `-O 4` is 64bppRGBAHalfFloat
# `-o 0` is linear transfer function
# `-j` for the Ultra HDR JPEG to be decoded
# Output is always named "outrgb.raw"
ultrahdr_app -m 1 -O 4 -o 0 -j ultra_hdr_image.jpg

This will give us a outrgb.raw file that's quite a bit larger than what we started with (my 3072x4080 test image went from a 3 MB JPEG to a 95 MB outrgb.raw). Next we need to convert these raw samples into a format that we can open in an image editor. Thankfully this is something that ImageMagick's convert tool is perfect for:

convert -define quantum:format=floating-point -depth 16 -size 3072x4080 \
    RGBA:outrgb.raw ultra_hdr_image.exr

Since outrgb.raw contains only raw samples, you also have to provide the correct image size.

OpenEXR (.exr) is probably the easiest format for working with HDR images as it keeps everything in linear format, though it's going to be just as large as our outrgb.raw file. If you're tight on space, Radiance HDR (.hdr) will be half the size and likely fine for something like this.

And, ta-da! We can open it up in whatever image tool can work with HDR images. I'm using Affinity Photo but tools like Kritta and Blender can also handle HDR / 32-bit linear colour spaces.

One of the big challenges is that there isn't many formats that support HDR on the web. AVIF does, but it seems cohost doesn't let you upload it3. So you'll just have to trust me that the reflection is almost painfully bright on a HDR display.


  1. a.k.a. "Your whites, whiter and your brights, brighter"

  2. Though it's far from what I'd call "user friendly"

  3. Though it was possible in the past (example)



It's that time where the gladiolus start blooming down the side of the house where mum snuck in some bulbs when they last visited from Australia.

They're short-lived, but they brighten up the house. Should have some yellow ones next month. 🌼🌷🌻

Also, this year's attempt at getting the raw DNG images from the Pixel 6 to develop correctly using Affinity Photo. The left is a regular JPEG and the right is a HDR AVIF.


Ā