After experimenting with several ways of doing tone-mapping in Photoshop, I’ve found the most consistent results so far following this procedure:
- set up the Rec. 2020 color space as in this screenshot (note it says Rec. 2100 but actually it’s using the Rec. 2020 gamma instead of the Rec. 2100 PQ transfer function, so it’s technically Rec. 2020)
- load the 8-bpp PNG and assign it into Rec. 2020 working space
- convert into sRGB and change working space back to sRGB
- use ‘Curves’ to apply a curve increasing contrast to desired levels while maintaining enough detail for the parts of the image you care about:
This seems to provide reasonable color reproduction so far, and the general ‘look’ of what I originally captured in HDR though in the SDR version I have to sacrifice either contrast or detail in certain areas due to the lower available peak brightness.
Probably the colorspace conversion can be scripted to save to manual fiddling, I’ll have to look into that.
Ideally there’d be a way to specifically do the PQ → sRGB conversion “correctly” with an explicit HDR->SDR compression of dynamic range on top, but eyeballing is good enough for my screenshots for now. 
Note that banding in the sky isn’t as bad as I expected because there’s dithering; I don’t know whether that was introduced by the MSFS rendering or the dynamic range compression from 10-bits into 8-bits, but it helps. Once you add JPEG compression in, though, you sometimes lose the dithering and banding returns.
I’m actually thinking now about making a purpose-built program to convert these 8-bit PNGs through the appropriate colorspace conversions with a couple sliders for customizing the curve used, and spit out PNG and JPEG output ready to post. 
Now I have to weigh the time commitment of thousands of screenshots versus writing one program.

I think I can do this in DirectX by creating an HDR10-compatible 32-bit surface out of the 8-bpp compressed PNG data, then sampling it into an FP16 scRGB surface, from which I can apply the custom transfer curve into normalized sRGB, and save that out to a regular SDR image.
However I’m not sure if the Rec. 2100 to scRGB color space or luminance range mapping are something that happens automatically or if I’d have to apply that myself with matrixes and a mapping function. More research for hobby project, HOORAY
(I did start this by saying I was just gonna skip HDR right? But it’s good. I actually like it, even in the basic form I got.
)
I found this FAQ thread on the nvidia forums:
which references a specific HDR viewer application available in the MS Store, “HDR + WCG Image Viewer”. I was able to get it to load up the JPEG XR files and display them correctly, nice! It includes an SDR export feature with tone mapping, but I’m not sure I like the resulting output as much as my manually adjusted files so far.
I’ll have to continue fiddling with this; if I do end up writing a helper program it should be able to pull from the JPEG XR instead of the PNG but will otherwise have to do similar things to do tone mapping I think.
I’ve started on a conversion program for my own usage, which I’ll make open-source in case anyone else finds it useful.
I’m writing it in Rust so it’s easy to distribute the compiled version as a standalone binary once complete.
Currently pulls from the 8-bpp PNG but once I figure out a library that can read JPEG XRs I’ll try to pull from that as source. Does proper colorspace and gamma conversion from BT Rec.2100 HDR space into non-normalized linear sRGB, applies a Reinhold tone-mapping to force HDR into SDR range, fixes any out of gamut colors by reducing their luminance until in range, and then applies sRGB gamma for saving out as a regular PNG.
Here’s a color-corrected shot:
And the original PNG capture with compressed dynamic range:
In the HDR original, the entire sky and mountains are above the SDR white point, as well as that bright white airplane skin! The Reinhold tone-mapping reduces contrast on brighter portions of the image, while preserving color, thus preserving some visible detail in those areas instead of blowing them out to solid white.
Note you can also “export to SDR” from the “HDR + WCG Image Viewer” app, which does similar (but not exactly the same) operations. If you’re happy with that procedure and its results, you don’t need to wait for my program! 
Nice, it’s coming along well. I added a 1.4 gamma curve before the HDR tone mapping and I’m really liking how it looks on my test images.
Each row here shows the raw data reinterpreted as sRGB (left), the proper HDR values clipped to SDR view (middle), and my own mapping to SDR sRGB on the right:
1 Like
Could you host one (or some) of your jxrs somewhere? I’d be interested to mess about with them myself.
1 Like
Absolutely, they’ll be in my github repo when I get it uploaded shortly. 
… and done! hdrfix/samples at main · bvibber/hdrfix · GitHub
Enjoy! 
1 Like
Making progress! I’ve updated my algorithm to map too-bright colors back into gamut by desaturating them (to maintain luminance and contrast) instead of darkening them (to maintain color). I’m pretty happy with the mappings now, next to finish support for reading the JPEG XR files which will retain slightly more detail than the PNGs.
Here’s a close-up of a blue DA62 in afternoon sunlight, showing desaturation in the brighter parts of the plane’s blue paint where the blue was still too brilliant to be mapped directly into SDR gamut after the HDR luminance was tone-mapped. This maintains the ‘3d shape’ of the plane better by retaining visible contrast on the skin of the plane that was previously getting reduced.
HDR JPEG XR version: https://github.com/brion/hdrfix/raw/main/samples/closeup-hdr.jxr
And here’s a city scene in the afternoon, with bright sunlight reflections in the river and a lot of sunlit haze on the surrounding ground and air in the distance. This algorithmic fix made a big difference on this image, where previously parts of the river ended up inverting in contrast compared to the less saturated cityscape around it.
HDR JPEG XR version: https://github.com/brion/hdrfix/raw/main/samples/portland-hdr.jxr
Oh yeah “I won’t bother with HDR, it’s too much trouble” hahahahahahaha 
Did some more adjustments on the conversion, and managed to get JPEG XR files loading as well as the PNGs.
However on the settings I’m using at least, I see very little difference between the PNG (8 bits per channel integer) and the JPEG XR (32 bits per channel float, possibly converted from an HDR10 10 bits per channel integer surface). There should be less banding in the sky and other bright color gradients, but those are already dithered pretty aggressively so they look ok in the 8-bit version.
Anyway, I’ll clean that up a bit later and add a mode that’ll watch your screenshots directory and auto-convert any new .jxr files that show up – this’ll make it “fire and forget”, you just grab your converted .png or .jpeg and post it if the default settings worked out.
Just an update on this – it’s coming along very well! Now produces JPEG output ready to post, can watch a directory for incoming .jxr files, and can do an automatic exposure adjustment based on an average (or partial average) of scene data if you like.
If using a fixed exposure adjustment, I find that going 1.5 stops down approximately matches the SDR rendering of MSFS (it boosts the base brightness of the entire scene for HDR output compared to SDR output).
If I can slap a simple GUI on the batch-converter later I’ll put up a downloadable release in case anyone would find it useful. 
GitHub repo: GitHub - bvibber/hdrfix: tool for converting HDR screenshots to SDR with suitable tone-mapping
Some of my samples as run with --auto-exposure=99.9% --hdr-max-99.9%
:
4 Likes
Hi, I just switched on HDR after SU5 and came across the “screenshot issue”. Stumbled into your thread and was wondering about the status of your little tool. As I am not a SW developer and Github expert, is your tool already ready to be used?
As I am running an AMD card, can it also work with the output the XBOX game bar creates mentioned above?
Thanks
I don’t know what the Xbox Game Bar creates, but if it’s JPEG XR and it’s the exact same pixel format, it might work. 
There’s no user interface yet, I run it through a batch file. I can make a binary build for you if you like, but you should check first to make sure you actually get JPEG XR (.jxr) files as your screenshots first, otherwise it likely will not help you. (At least not in its current state.)
Ok, thanks for your feedback. I will come back to you once I am certain what files I get.
But using the batch file would also be perfectly fine for me.
1 Like
Great, just let me know! If it’s not a .jxr, I might still be able to figure out how to read it though, it’s probably another common format I can find a codec for. 
Hi, I think I built this correctly on a Linux machine a few weeks ago. However I got the following error when I fed it a jxr file from a Game Bar HDR capture.
user@dev:~/src/hdrfix/target/release$ ./hdrfix ~/msfs.jxr msfs.jpg
/home/user/msfs.jxr -> msfs.jpg
Error: Unsupported pixel format
Let me know if you need any info, or perhaps we should take this off this forum and open it as an issue on your repo. Thanks.
1 Like
Yeah it’s probably just a different pixel format (like, 10-bit RGB instead of 32-bit float RGB), in which case I should be able to modify things to support it, while using the same library. Can you open an issue on the repo and attach a sample file? I can test from there.
It might take me a couple days, I’ve got a busy week this week, but I hope it won’t be too difficult. 
1 Like
Done. Thanks much for looking into this.
1 Like
Thank you for responding so quickly to add support for the Game Bar JXR format. The new version works great!
1 Like
Woohoo! You’re welcome, thanks for helping test. 
So, I understand it works with the Xbox Game Bar now?
Can you point me to the files? Much appreciated
Edit: Ok, downloading the Zip from Github.
I think I need a short advice how to proceed once I have downloaded and extracted the hdrfix-main.
Thank you