LUT baking of HDR images in Krita

If you have an HDR setup for Krita and you have ever tried to share your HDR paintings or animations with anyone, you know it might not be an easy task. Krita’s conversion HDR -> sRGB is lossy, colors become white or washed out. In most cases, the image just looks damaged.

HDR image naively converted to SDR

HDR image converted to SDR using this method

There are some ways to work around this. One of them is to use a program that can actually do a proper LUT baking. But that would require learning a new program, so scratch that, we’re gonna do it in Krita.

Open your precious HDR painting. (For animation the tutorial is basically the same). Make sure your last progress is safely saved somewhere as .kra! You can even make a copy and open the copy just in case – because following this tutorial will for sure damage your data in the image, so better to have a backup.

If you followed the official guideline, your image is probably in Rec2020-elle-V4-g10.icc color space. That’s a good color space for painting, but not for LUT baking. The thing is, this color space has point 1.0 in some arbitrary location. There is no way to get the brightest white available on HDR display below the 1.0 point in the elle color space. And considering that our filters just cut out all the data outside of (0; 1) range, most of our colors data would be lost. Just like converting the image without adjusting it first.

Because of that, the first step is converting your image to Rec2020-PQ color space (the one with a very long name with different acronyms). It has a 1.0 point around the whitest white on your display, which is enough in this case (what you see as white, will be seen as white in sRGB).

Create a filter layer. I would advise using Color Adjustment Curves since they clearly show what’s going on. You can adjust all channels separately or just use RGBA curve. I used RGBA for this example.

The main idea is to squish the color range. The easiest way to do it is to just move the end point a lot lower and the start point a bit higher (colors that are lost are usually the brightest one, hence you need a stronger conversion on them). If you’re feeling adventurous, I would suggest you to try to adjust it in a bit more advanced manner – for example simple curve (if you don’t see it, it’s a lower left quadrant circular arc, as Unicode chars sheet informed me) will increase contrast, and S-shaped curve will both increase contrast and ensure that bright parts will still be quite bright.

Screenshot showing the first curve

The key to success here is… the fact that Overview docker still doesn’t support HDR. There is a high chance it will change with Qt 5.13 or Qt 5.14 where 16bit QImages are introduced, which will solve all of our HDR preview issues: Bug 406698: Tools have SDR previews on HDR display. Fortunately till then, we’ll free to use it as our SDR glasses: whatever you see in the Overview docker, it’s exactly the same to what you’ll see after converting. Make the Overview docker big and make sure it shows all the colors and details you want to include in the final picture. At first, just make sure the image is dark enough to see all colors; then make sure the contrast and saturation are the best possible. (Protip: sometimes colors are brighter after conversion than it looked before; I had it which the central part of this picture, it was dull orange in HDR, after conversion it started to be nicely yellowish).

Screenshot showing the second curve

Screenshot showing the third curve

After you created all of those filter layers (you don’t have to create multiple, but you’ll probably end up with more than one at some point), don’t convert the image yet. It won’t work. Krita will convert all the layers below color adjustment layers, they will get white where you want your colors and saturation, and then color adjustment curves will be useless (and Krita helpfully makes them broken, too). On top of that when I tried to do this and quickly pressed undo, seeing the disaster my picture became, the undo didn’t work properly; Dmitry told me that it’s because some of his code isn’t in the development version yet – which means the release version doesn’t have it either, but maybe the next release will have a proper undo. But don’t rely on it – backup your files before doing anything potentially disastrous!

To avoid the trouble, just right-click on the Layers docker and select “New layer from Visible”. If you have all of your backups (check them!), you can just remove all of the layers and then finally convert the image to sRGB color space. Voila! The process is done.

(Previously published on LUT baking of Krita HDR images blog post)