retract the HLG/PQ APIs a bit
Rewrite skcms.h to only mention the encoded->linear forward functions,
just like we do for sRGBish transfer functions, and just as
skcms_Transform() expects. There's little need for anyone to get their
hands on an inverse-PQ or inverse-HLG skcms_TransferFunction except
internally inverting in skcms_Transform() or for testing.
Change-Id: If52b053f8dc0a20659c3e0953170221bdffeeeba
Reviewed-on: https://skia-review.googlesource.com/c/skcms/+/248202
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/skcms.cc b/skcms.cc
index 76adcad..3873d6e 100644
--- a/skcms.cc
+++ b/skcms.cc
@@ -168,14 +168,6 @@
return true;
}
-bool skcms_TransferFunction_makeHLGinvish(skcms_TransferFunction* tf,
- float R, float G,
- float a, float b, float c) {
- *tf = { TFKind_marker(HLGinvish), R,G, a,b,c, 0 };
- assert(classify(*tf) == HLGinvish);
- return true;
-}
-
bool skcms_TransferFunction_makeHLGish(skcms_TransferFunction* tf,
float R, float G,
float a, float b, float c) {
diff --git a/skcms.h b/skcms.h
index bd3a96e..b73eeb3 100644
--- a/skcms.h
+++ b/skcms.h
@@ -52,47 +52,31 @@
skcms_TransferFunction*);
// We can jam a couple alternate transfer function forms into skcms_TransferFunction,
-// including those matching the general form of the SMPTE ST 2084 PQ function and its inverse:
+// including those matching the general forms of the SMPTE ST 2084 PQ function or HLG.
//
-// max(A + B|x|^C, 0)
-// tf(x) = sign(x) * (------------------) ^ F
- // (D + E|x|^C)
+// PQish:
+// max(A + B|encoded|^C, 0)
+// linear = sign(encoded) * (------------------------) ^ F
+// D + E|encoded|^C
SKCMS_API bool skcms_TransferFunction_makePQish(skcms_TransferFunction*,
float A, float B, float C,
float D, float E, float F);
-
-static inline bool skcms_TransferFunction_makePQ(skcms_TransferFunction* tf) {
- return skcms_TransferFunction_makePQish(tf, -107/128.0f, 1.0f, 32/2523.0f
- , 2413/128.0f, -2392/128.0f, 8192/1305.0f);
-}
-static inline bool skcms_TransferFunction_makePQinv(skcms_TransferFunction* tf) {
- return skcms_TransferFunction_makePQish(tf, 107/128.0f, 2413/128.0f, 1305/8192.0f
- , 1.0f, 2392/128.0f, 2523/ 32.0f);
-}
-
-// skcms_TransferFunction also supports functions of the form of HLG's inverse...
-//
-// { sign(linear) * ( R|linear|^G ) when 0 <= |linear| <= 1
-// encoded = { sign(linear) * ( a ln(|linear|-b) + c ) when 1 < |linear|
-SKCMS_API bool skcms_TransferFunction_makeHLGinvish(skcms_TransferFunction*,
- float R, float G,
- float a, float b, float c);
-
-// ... and of the form of HLG itself, factored to take the same five parameters.
-//
+// HLGish:
// { sign(encoded) * ( (|encoded|/R)^(1/G) ) when 0 <= |encoded| <= R
// linear = { sign(encoded) * ( e^( (|encoded|-c)/a ) + b ) when R < |encoded|
SKCMS_API bool skcms_TransferFunction_makeHLGish(skcms_TransferFunction*,
float R, float G,
float a, float b, float c);
-static inline bool skcms_TransferFunction_makeHLG(skcms_TransferFunction* tf) {
- return skcms_TransferFunction_makeHLGish(tf,
- 0.5f, 0.5f , 0.17883277f, 0.28466892f, 0.55991073f);
+// PQ mapping encoded [0,1] to linear [0,1].
+static inline bool skcms_TransferFunction_makePQ(skcms_TransferFunction* tf) {
+ return skcms_TransferFunction_makePQish(tf, -107/128.0f, 1.0f, 32/2523.0f
+ , 2413/128.0f, -2392/128.0f, 8192/1305.0f);
}
-static inline bool skcms_TransferFunction_makeHLGinv(skcms_TransferFunction* tf) {
- return skcms_TransferFunction_makeHLGinvish(tf,
- 0.5f, 0.5f , 0.17883277f, 0.28466892f, 0.55991073f);
+// HLG mapping encoded [0,1] to linear [0,12].
+static inline bool skcms_TransferFunction_makeHLG(skcms_TransferFunction* tf) {
+ return skcms_TransferFunction_makeHLGish(tf, 0.5f, 0.5f
+ , 0.17883277f, 0.28466892f, 0.55991073f);
}
// Unified representation of 'curv' or 'para' tag data, or a 1D table from 'mft1' or 'mft2'
diff --git a/tests.c b/tests.c
index b372a33..c72fa70 100644
--- a/tests.c
+++ b/tests.c
@@ -1439,8 +1439,8 @@
static void test_HLG() {
skcms_TransferFunction enc, dec;
- expect(skcms_TransferFunction_makeHLGinv(&enc));
- expect(skcms_TransferFunction_makeHLG (&dec));
+ expect(skcms_TransferFunction_makeHLG(&dec));
+ expect(skcms_TransferFunction_invert(&dec, &enc));
// Spot check the lower half of the curve.
// Linear 0 encodes as 0.5*(0)^0.5 == 0.
@@ -1506,8 +1506,10 @@
static void test_PQ_invert() {
skcms_TransferFunction pqA, invA, invB;
- expect(skcms_TransferFunction_makePQ (&pqA) );
- expect(skcms_TransferFunction_makePQinv(&invA));
+ expect(skcms_TransferFunction_makePQ(&pqA));
+ // PQ's inverse is actually also PQish, so we can write out its expected value here.
+ expect(skcms_TransferFunction_makePQish(&invA, 107/128.0f, 2413/128.0f, 1305/8192.0f
+ , 1.0f, 2392/128.0f, 2523/ 32.0f));
expect(skcms_TransferFunction_invert(&pqA, &invB));
// a,b,d,e really just negate and swap around,
@@ -1550,45 +1552,31 @@
}
static void test_HLG_invert() {
- skcms_TransferFunction hlgA, invA, invB;
+ skcms_TransferFunction hlg, inv;
- expect(skcms_TransferFunction_makeHLG (&hlgA) );
- expect(skcms_TransferFunction_makeHLGinv(&invA));
- expect(skcms_TransferFunction_invert(&hlgA, &invB));
+ expect(skcms_TransferFunction_makeHLG(&hlg));
+ // Unlike PQ, we can't create HLG's inverse directly, only via _invert().
+ expect(skcms_TransferFunction_invert(&hlg, &inv));
- // Like PQ above, some of these values are expected
- // to be exact, and some of them we're just getting
- // lucky with that they happen to round trip exactly.
+ skcms_TransferFunction back;
+ expect(skcms_TransferFunction_invert(&inv, &back));
- expect(invA.g == invB.g); // Is this still HLGinvish?
- expect(invA.a == invB.a); // Lucky.
- expect(invA.b == invB.b); // Lucky.
- expect(invA.c == invB.c); // Lucky.
- expect(invA.d == invB.d); // Exact.
- expect(invA.e == invB.e); // Exact.
- expect(invA.f == invB.f); // Exact (zero).
-
- // ... and invert back to HLG.
- // This tests a slightly different code path (really very similar).
- skcms_TransferFunction hlgB;
- expect(skcms_TransferFunction_invert(&invB, &hlgB));
-
- expect(hlgA.g == hlgB.g);
- expect(hlgA.a == hlgB.a);
- expect(hlgA.b == hlgB.b);
- expect(hlgA.c == hlgB.c);
- expect(hlgA.d == hlgB.d);
- expect(hlgA.e == hlgB.e);
- expect(hlgA.f == hlgB.f);
+ expect(hlg.g == back.g);
+ expect(hlg.a == back.a);
+ expect(hlg.b == back.b);
+ expect(hlg.c == back.c);
+ expect(hlg.d == back.d);
+ expect(hlg.e == back.e);
+ expect(hlg.f == back.f);
// HLG functions invert between two different forms.
- expect(hlgA.g != invA.g);
+ expect(hlg.g != inv.g);
- skcms_Curve hlg_curve = {{0, hlgA}},
- inv_curve = {{0, invA}};
+ skcms_Curve hlg_curve = {{0, hlg}},
+ inv_curve = {{0, inv}};
- expect(skcms_AreApproximateInverses(&hlg_curve, &invA));
- expect(skcms_AreApproximateInverses(&inv_curve, &hlgA));
+ expect(skcms_AreApproximateInverses(&hlg_curve, &inv));
+ expect(skcms_AreApproximateInverses(&inv_curve, &hlg));
}
int main(int argc, char** argv) {