QColorTransferGeneric: fix the BT.2100 PQ EOTF
The PQ EOTF formula for BT.2100 [1][2] was incorrect. Fix it; while at it, rename the variables to match the symbols used in the original formula. The inverse EOTF was correct, but also rename the variables there (for the same reason). [1] https://www.itu.int/rec/R-REC-BT.2100-2-201807-I/en [2] https://en.wikipedia.org/wiki/Perceptual_quantizer#Technical_details Change-Id: I6ce3a609824bee82053a16b3ff3cfc7cb396ce8f Pick-to: 6.8 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> (cherry picked from commit a7ff4679facb9a44dff8b63a7e461ababa6aedfb) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
b9169c1210
commit
35c18eba64
@ -82,18 +82,31 @@ private:
|
||||
constexpr static float m_hlg_b = 1.f - (4.f * m_hlg_a);
|
||||
constexpr static float m_hlg_c = 0.55991073f; // 0.5 - a * ln(4 * a)
|
||||
|
||||
// BT.2100-2 Reference PQ EOTF and inverse (see Table 4)
|
||||
// PQ to linear [0-1] -> [0-64]
|
||||
static float pqToLinear(float x)
|
||||
static float pqToLinear(float e)
|
||||
{
|
||||
x = std::pow(x, 1.f / m_pq_m2);
|
||||
return std::pow((m_pq_c1 - x) / (m_pq_c3 * x - m_pq_c2), (1.f / m_pq_m1)) * m_pq_f;
|
||||
// m2-th root of E'
|
||||
const float eRoot = std::pow(e, 1.f / m_pq_m2);
|
||||
// rational transform
|
||||
const float yBase = (std::max)(eRoot - m_pq_c1, 0.0f) / (m_pq_c2 - m_pq_c3 * eRoot);
|
||||
// calculate Y = yBase^(1/m1)
|
||||
const float y = std::pow(yBase, 1.f / m_pq_m1);
|
||||
// scale Y to Fd
|
||||
return y * m_pq_f;
|
||||
}
|
||||
|
||||
// PQ from linear [0-64] -> [0-1]
|
||||
static float pqFromLinear(float x)
|
||||
static float pqFromLinear(float fd)
|
||||
{
|
||||
x = std::pow(x * (1.f / m_pq_f), m_pq_m1);
|
||||
return std::pow((m_pq_c1 + m_pq_c2 * x) / (1.f + m_pq_c3 * x), m_pq_m2);
|
||||
// scale Fd to Y
|
||||
const float y = fd * (1.f / m_pq_f);
|
||||
// yRoot = Y^m1 -- "root" because m1 is <1
|
||||
const float yRoot = std::pow(y, m_pq_m1);
|
||||
// rational transform
|
||||
const float eBase = (m_pq_c1 + m_pq_c2 * yRoot) / (1.f + m_pq_c3 * yRoot);
|
||||
// calculate E' = eBase^m2
|
||||
return std::pow(eBase, m_pq_m2);
|
||||
}
|
||||
|
||||
constexpr static float m_pq_c1 = 107.f / 128.f; // c3 - c2 + 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user