Log in

View Full Version : Converting 2160p BT.2020 to 1080p BT.709, along with tone mapping


GeoffreyA
25th October 2024, 14:31
Good afternoon.

In order to convert some HDR 4K films to SDR 1080p, particularly The Lord of the Rings Theatrical, I put together the following script and have been experimenting with it for a couple of months. It seems to work well; but I wonder if doing the tone mapping while the primaries are still at BT.2020 is the right way to proceed. Apart from that, does the process seem correct?

(As a side note, FFmpeg also works well and the result is slightly more saturated. On Interstellar, though, it falls flat when Gargantua takes the stage, showing discolouration. The issue seems to be with zscale. So, I prefer using VapourSynth and fmtconv, whose results are better and closer to the official Blu-ray versions.)

from vapoursynth import core

clip = core.lsmas.LWLibavSource(filename)

clip = clip.fmtc.bitdepth(bits=32)
clip = clip.fmtc.resample(css="444")
clip = clip.fmtc.matrix(mats="2020", matd="rgb")
clip = clip.fmtc.transfer(transs="2084", transd="linear", match=2)

#clip = clip.tonemap.Reinhard(exposure=1, peak=100)
clip = clip.tonemap.Hable(exposure=1.9)

clip = clip.fmtc.resample(w=1920, h=1080, kernel="spline36")

clip = clip.fmtc.primaries(prims="2020", primd="709")
clip = clip.fmtc.transfer(transs="linear", transd="709")
clip = clip.fmtc.matrix(mats="rgb", matd="709")
clip = clip.fmtc.resample(css="420")
clip = clip.fmtc.bitdepth(bits=8)

clip.set_output()

A sample result: https://we.tl/t-VMGijyoSKN

Selur
25th October 2024, 20:27
When using tonemap (I prefer DGHDRtoSDR or placebo.Tonemap) I use:
# color adjustment using ToneMap
clip = core.resize.Bilinear(clip=clip, format=vs.RGBS, range_in_s="limited", matrix_in_s="2020ncl", primaries_in_s="2020", primaries_s="2020", transfer_in_s="st2084", transfer_s="linear",dither_type="none", nominal_luminance=1000)
clip = core.tonemap.Reinhard(clip=clip)
#clip = core.tonemap.Mobius(clip=clip)
#clip = core.tonemap.Hable(clip=clip)
clip = core.resize.Bilinear(clip=clip, format=vs.YUV420P8, matrix_s="709", primaries_s="709",range_s="limited", transfer_s="709", transfer_in_s="linear", range_in_s="limited", dither_type="ordered")

Cu Selur

GeoffreyA
26th October 2024, 07:43
Thanks, Selur. Yes, I did find issues with tonemap. However, I believe there was also a problem with DGHDRtoSDR, which brought the faintest of a green tint, and also, the opaqueness of the plug-in's working is less than ideal.

I see that you are doing the tone mapping with primaries at BT.2020. That's what also works for me. When I tried using CIE XYZ, there was a purple tint in one clip (Samsung's "Travel with My Pet" sample).