Skip to content
This repository has been archived by the owner on Mar 10, 2023. It is now read-only.

Add support for HDR transfer functions #52

Closed
stevenrobertson opened this issue Dec 4, 2015 · 3 comments
Closed

Add support for HDR transfer functions #52

stevenrobertson opened this issue Dec 4, 2015 · 3 comments
Labels

Comments

@stevenrobertson
Copy link

Hey, Lattice is great!

There are two transfer functions which I think will become increasingly important in the near future, and which it would be awesome to see Lattice support: SMPTE 2084 and HLG.

Background if you aren't already familiar:

SMPTE 2084 (Dolby PQ) is often parameterized based on the peak display luminance. PQ stands out because its codepoints map to specific luminance levels - for instance, the codepoint (512, 512, 512) maps to a gray color that is intended to be 92.2 nits of brightness at the output device. Since modern devices do not go anywhere close to the 10,000 nit peak code value, each device will be responsible for interpreting how to handle out-of-range values, and nobody's releasing content that is mastered for the full 10,000 nit range, most of the time a workflow will pick a reasonable peak value (say, 1,000 nits), and map the highest attainable gamma codepoint in the input space to the same value in the output space.

So, with a target peak luminance of 1,000 nits, an input gamma value of 1.0 would be mapped to an output SMPTE 2084 value of 0.751827096247.

Here's a publicly accessible link:
https://www.smpte.org/sites/default/files/23-1615-TS7-2-IProc02-Miller.pdf

and an example implementation taken from an IPython notebook that I've been using to make test cards:

class SMPTE2084TransferFunc(object):
    name = 'smpte-st-2084'
    def __init__(self, luminance_cap=1000):
        self.luma = luminance_cap
        self.factor = luminance_cap / 10000.

    def oetf(self, v):
        ve = (v * self.factor) ** 0.1593017578125
        return ((0.8359375 + 18.8515625 * ve) / (1 + 18.6875 * ve)) ** 78.84375

    def eotf(self, v):
        ve = v ** (1 / 78.84375)
        return (max(0, ve - 0.8359375) / (18.8515625 - 18.6875 * ve)) ** (1 / 0.1593017578125) / self.factor

Hybrid Log-Gamma (ARIB STD-B67) is an alternative HDR proposal that's designed to still be efficient-ish on the same metric that PQ uses, but also to not look terrible when viewed on a traditional gamma display and to not require additional metadata. HLG also has a parameterization, called system gamma, which is used to adapt content for various display environments; there's a recommended application of system gamma as a ratio of display peak to ambient light intensity.

Here's a paper (with some older values):
http://www.bbc.co.uk/rd/publications/whitepaper309

Here's the standard where the values have been locked down:
http://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf

And here's the example from that IPython notebook:

class ARIBStdB67TransferFunc(object):
    name = 'arib-std-b67'
    def __init__(self, system_gamma=1.25):
        self.system_gamma = system_gamma

    a = 0.17883277
    b = 0.28466892
    c = 0.55991073
    Lmax = 12

    def oetf(self, v):
        # Note that normally we wouldn't apply system gamma to the input, but 
        # since we are after all doing gamma tests...
        E = v ** (1 / self.system_gamma) * self.Lmax
        if E <= 1:
            E_ = 0.5 * np.sqrt(E)
        else:
            E_ = self.a * np.log(E - self.b) + self.c
        return E_

    def eotf(self, E_):
        if E_ <= 0.5:
            v_ = (E_ * 2) ** 2
        else:
            v_ = np.exp((E_ - self.c) / self.a) + self.b
        return (v_ / self.Lmax) ** self.system_gamma
@gregcotten
Copy link
Member

Hi Steven,

Thanks so much for this! We have rudimentary PQ support but no support at all for HLG. I'm currently in the process of adding these functions into the colorspace converter.

@gregcotten
Copy link
Member

By the way, would you have any idea as to why Blackmagic's PQ HDR LUTs are intended for boundaries outside 0 to 1?

@stevenrobertson
Copy link
Author

It's a philosophical choice on their part. If you import footage into
Resolve 12.2, by default the peak of that footage gets seated at 100 nits
in the PQ scale, which is "SDR peak brightness". (Except almost all modern
SDR televisions have shot past 100 nits long ago.)

The result tends to be a much more highlight-focused workflow with a darker
average frame luminance in my experience, which definitely makes something
say "I'm HDR!" and will render better on current-gen TVs which can only do
full brightness over a small area. But that look may not be the most
natural or enduring use of HDR as we move from tech demos to actual
narrative content.

On Tue, Jan 5, 2016 at 4:23 PM, Greg Cotten notifications@github.com
wrote:

By the way, would you have any idea as to why Blackmagic's PQ HDR LUTs are
intended for boundaries outside 0 to 1?


Reply to this email directly or view it on GitHub
#52 (comment)
.

@wilg wilg added the feature label Apr 27, 2019
@wilg wilg closed this as not planned Won't fix, can't repro, duplicate, stale Mar 10, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants