[babl] babl: in BablTRC, use BablPolynomial to approximate gamma func.



commit 5987599a6b44e3e9de03826407b2907827226df8
Author: Ell <ell_se yahoo com>
Date:   Sun Sep 10 11:38:01 2017 -0400

    babl: in BablTRC, use BablPolynomial to approximate gamma func.
    
    Use BablPolynomial to approximate gamma functions of TRCs over the
    (0, 1) range, for FORMULA_GAMMA and FORMULA_SRGB TRCs.
    
    Use generic FORMULA_GAMMA TRCs for 1.8 and 2.2 gammas, instead of
    specialized versions.

 babl/babl-icc.c |    2 -
 babl/babl-trc.c |  274 ++++++++++++++----------------------------------------
 babl/babl-trc.h |    9 ++-
 3 files changed, 78 insertions(+), 207 deletions(-)
---
diff --git a/babl/babl-icc.c b/babl/babl-icc.c
index d6857b2..0bf74cb 100644
--- a/babl/babl-icc.c
+++ b/babl/babl-icc.c
@@ -417,8 +417,6 @@ switch (trc->type)
     icc_write (u32, state->o + 8, 0);
     break;
   case BABL_TRC_FORMULA_GAMMA:
-  case BABL_TRC_GAMMA_1_8:
-  case BABL_TRC_GAMMA_2_2:
     icc_allocate_tag (state, name, 14);
     icc_write (sign, state->o, "curv");
     icc_write (u32, state->o + 4, 0);
diff --git a/babl/babl-trc.c b/babl/babl-trc.c
index 7fa79f1..1a98889 100644
--- a/babl/babl-trc.c
+++ b/babl/babl-trc.c
@@ -18,6 +18,12 @@
 
 #define MAX_TRCS   100
 
+/* FIXME: choose parameters more intelligently */
+#define POLY_GAMMA_X0     (  0.5 / 255.0)
+#define POLY_GAMMA_X1     (254.5 / 255.0)
+#define POLY_GAMMA_DEGREE 6
+#define POLY_GAMMA_SCALE  2
+
 #include "config.h"
 #include "babl-internal.h"
 #include "base/util.h"
@@ -371,51 +377,61 @@ static inline float babl_powf (float x, float y)
   return 0.0f;
 }
 
+static inline float _babl_trc_gamma_to_linear (const Babl *trc_, float value)
+{
+  BablTRC *trc = (void*)trc_;
+  if (value >= trc->poly_gamma_to_linear_x0 &&
+      value <= trc->poly_gamma_to_linear_x1)
+    {
+      return babl_polynomial_eval (&trc->poly_gamma_to_linear, value);
+    }
+  else
+    {
+      return babl_powf (value, trc->gamma);
+    }
+}
 
-static inline void _babl_trc_gamma_to_linear_buf (const Babl *trc_, const float *in, float *out, int in_gap, 
int out_gap, int components, int count)
+static inline float _babl_trc_gamma_from_linear (const Babl *trc_, float value)
 {
   BablTRC *trc = (void*)trc_;
-  float gamma = trc->gamma;
+  if (value >= trc->poly_gamma_from_linear_x0 &&
+      value <= trc->poly_gamma_from_linear_x1)
+    {
+      return babl_polynomial_eval (&trc->poly_gamma_from_linear, value);
+    }
+  else
+    {
+      return babl_powf (value, trc->rgamma);
+    }
+}
+
+static inline void _babl_trc_gamma_to_linear_buf (const Babl *trc_, const float *in, float *out, int in_gap, 
int out_gap, int components, int count)
+{
   int i, c;
   for (i = 0; i < count; i ++)
     for (c = 0; c < components; c ++)
-      out[out_gap * i + c] = babl_powf (in[in_gap *i + c], gamma);
+      out[out_gap * i + c] = _babl_trc_gamma_to_linear (trc_, in[in_gap *i + c]);
 }
 
 static inline void _babl_trc_gamma_from_linear_buf (const Babl *trc_, const float *in, float *out, int 
in_gap, int out_gap, int components, int count)
 {
-  BablTRC *trc = (void*)trc_;
-  float gamma = trc->rgamma;
   int i, c;
   for (i = 0; i < count; i ++)
     for (c = 0; c < components; c ++)
-      out[out_gap * i + c] = babl_powf (in[in_gap *i + c], gamma);
-}
-
-static inline float _babl_trc_gamma_from_linear (const Babl *trc_, float value)
-{
-  BablTRC *trc = (void*)trc_;
-  return babl_powf (value, trc->rgamma);
-}
-
-static inline float _babl_trc_gamma_to_linear (const Babl *trc_, float value)
-{
-  BablTRC *trc = (void*)trc_;
-  return babl_powf (value, trc->gamma);
+      out[out_gap * i + c] = _babl_trc_gamma_from_linear (trc_, in[in_gap *i + c]);
 }
 
 static inline float _babl_trc_formula_srgb_from_linear (const Babl *trc_, float value)
 {
   BablTRC *trc = (void*)trc_;
   float x= value;
-  float g = trc->lut[0];
   float a = trc->lut[1];
   float b = trc->lut[2];
   float c = trc->lut[3];
   float d = trc->lut[4];
   if (x > c * d)  // XXX: verify that this math is the correct inverse
   {
-    float v = babl_powf (x, 1.0/g);
+    float v = _babl_trc_gamma_from_linear ((Babl *) trc, x);
     v = (v-b)/a;
     if (v < 0.0 || v >= 0.0)
       return v;
@@ -430,7 +446,6 @@ static inline float _babl_trc_formula_srgb_to_linear (const Babl *trc_, float va
 {
   BablTRC *trc = (void*)trc_;
   float x= value;
-  float g = trc->lut[0];
   float a = trc->lut[1];
   float b = trc->lut[2];
   float c = trc->lut[3];
@@ -438,125 +453,11 @@ static inline float _babl_trc_formula_srgb_to_linear (const Babl *trc_, float va
 
   if (x >= d)
   {
-    return babl_powf (a * x + b, g);
+    return _babl_trc_gamma_to_linear ((Babl *) trc, a * x + b);
   }
   return c * x;
 }
 
-
-static inline float _babl_trc_gamma_1_8_to_linear (const Babl *trc_, float x)
-{
-  if (x >= 0.01f && x < 0.7f)
-  {
-    double u = -1.326432065236105e+1;
-    u = u * x + 7.7192973347868776e+1;
-    u = u * x + -1.9639662782311719e+2;
-    u = u * x + 2.8719828602066411e+2;
-    u = u * x + -2.6718118019754855e+2;
-    u = u * x + 1.6562450069335532e+2;
-    u = u * x + -6.9988172743274441e+1;
-    u = u * x + 2.0568254985551865e+1;
-    u = u * x + -4.5302829214271245;
-    u = u * x + 1.7636048338730889;
-    u = u * x + 1.3015451332543148e-2;
-    return u * x + -5.4445726922508747e-5;
-  }
-  else if (x >= 0.7f && x < 1.4f)
-  {
-    double u = 2.4212422421184617e-3;
-    u = u * x + -2.0853930731707795e-2;
-    u = u * x + 8.2416801461966525e-2;
-    u = u * x + -2.1755799369117727e-1;
-    u = u * x + 1.0503926510667593;
-    u = u * x + 1.1196374095271941e-1;
-    return u * x + -8.7825075945914206e-3;
-  }
-  return babl_powf (x, 1.8f);
-}
-
-static inline float _babl_trc_gamma_1_8_from_linear (const Babl *trc_, float x)
-{
-  if (x >= 0.01f && x < 0.25f)
-  {
-    double u = -7.0287082190390287e+7;
-    u = u * x + 9.6393346352028194e+7;
-    u = u * x + -5.734540040993472e+7;
-    u = u * x + 1.9423130902481005e+7;
-    u = u * x + -4.1360185772523716e+6;
-    u = u * x + 5.7798684366021459e+5;
-    u = u * x + -5.3914765738125787e+4;
-    u = u * x + 3.3827381495697474e+3;
-    u = u * x + -1.4758049734050082e+2;
-    u = u * x + 6.34823684277896;
-    return u * x + 2.5853366952641552e-2;
-  } else if (x >= 0.25f && x < 1.1f)
-  {
-    double u = -1.0514013917303294;
-    u = u * x + 7.7742547018698687;
-    u = u * x + -2.5688463052927626e+1;
-    u = u * x + 5.009448068094152e+1;
-    u = u * x + -6.4160579394623318e+1;
-    u = u * x + 5.6890996491836047e+1;
-    u = u * x + -3.5956430472666212e+1;
-    u = u * x + 1.6565821666356617e+1;
-    u = u * x + -5.8508167212560416;
-    u = u * x + 2.2859969154731878;
-    return u * x + 9.6140522367339399e-2;
-  }
-  return babl_powf (x, 1.0f/1.8f);
-}
-
-static inline float _babl_trc_gamma_2_2_to_linear (const Babl *trc_, float x)
-{
-  if (x >= 0.01f && x < 1.0f)
-  {
-    double u = -1.7565198334207539;
-    u = u * x + 9.4503605497836926;
-    u = u * x + -2.2016178903082791e+1;
-    u = u * x + 2.9177361786084179e+1;
-    u = u * x + -2.4368251609523336e+1;
-    u = u * x + 1.3522663223248737e+1;
-    u = u * x + -5.253344907664925;
-    u = u * x + 1.7182864905042889;
-    u = u * x + 5.2860458501353106e-1;
-    u = u * x + -3.0000031884069502e-3;
-    return u * x + 1.6952727496833812e-5;
-  }
-  return babl_powf (x, 2.2f);
-}
-
-static inline float _babl_trc_gamma_2_2_from_linear (const Babl *trc_, float x)
-{
-  if (x >= 0.01f && x < 0.25f)
-  {
-    double u = -1.1853049266795914e+8;
-    u = u * x + 1.6235355750617304e+8;
-    u = u * x + -9.6434183855508922e+7;
-    u = u * x + 3.2595749146174438e+7;
-    u = u * x + -6.9216734175519044e+6;
-    u = u * x + 9.6337373983643336e+5;
-    u = u * x + -8.9295299887376452e+4;
-    u = u * x + 5.5387559329470092e+3;
-    u = u * x + -2.3522564268245811e+2;
-    u = u * x + 8.8234901614165394;
-    return u * x + 5.3919966190648492e-2;
-  } else if (x >= 0.25f && x < 1.0f)
-  {
-    double u = -2.1065242890384543e-1;
-    u = u * x + 1.7554867367832886;
-    u = u * x + -6.6371047248064382;
-    u = u * x + 1.5049549954517457e+1;
-    u = u * x + -2.279671781745644e+1;
-    u = u * x + 2.4331499227325978e+1;
-    u = u * x + -1.8839523095731037e+1;
-    u = u * x + 1.0802279176589768e+1;
-    u = u * x + -4.7776729355620852;
-    u = u * x + 2.1410886948010769;
-    return u * x + 1.817672123838504e-1;
-  }
-  return babl_powf (x, 1.0/2.2);
-}
-
 static inline float _babl_trc_srgb_to_linear (const Babl *trc_, float value)
 {
   return babl_gamma_2_2_to_linearf (value);
@@ -609,30 +510,6 @@ static inline void _babl_trc_from_linear_buf_generic (const Babl *trc_,
       out[out_gap * i + c] = trc->fun_from_linear (trc_, in[in_gap * i + c]);
 }
 
-static inline void _babl_trc_gamma_1_8_from_linear_buf (const Babl *trc_,
-                                                        const float *in, float *out,
-                                                        int in_gap, int out_gap,
-                                                        int components,
-                                                        int count)
-{
-  int i, c;
-  for (i = 0; i < count; i ++)
-    for (c = 0; c < components; c ++)
-      out[i * out_gap + c] = _babl_trc_gamma_1_8_from_linear (trc_, in[i * in_gap + c]);
-}
-
-static inline void _babl_trc_gamma_2_2_from_linear_buf (const Babl *trc_,
-                                                        const float *in, float *out,
-                                                        int in_gap, int out_gap,
-                                                        int components,
-                                                        int count)
-{
-  int i, c;
-  for (i = 0; i < count; i ++)
-    for (c = 0; c < components; c ++)
-      out[i * out_gap + c] = _babl_trc_gamma_2_2_from_linear (trc_, in[i * in_gap + c]);
-}
-
 static inline void _babl_trc_linear_buf (const Babl *trc_,
                                          const float *in, float *out,
                                          int in_gap, int out_gap,
@@ -645,30 +522,6 @@ static inline void _babl_trc_linear_buf (const Babl *trc_,
       out[i * out_gap + c] = in[i * in_gap + c];
 }
 
-static inline void _babl_trc_gamma_1_8_to_linear_buf (const Babl *trc_,
-                                                      const float *in, float *out,
-                                                      int in_gap, int out_gap,
-                                                      int components,
-                                                      int count)
-{
-  int i, c;
-  for (i = 0; i < count; i ++)
-    for (c = 0; c < components; c ++)
-      out[i * out_gap + c] = _babl_trc_gamma_1_8_to_linear (trc_, in[i * in_gap + c]);
-}
-
-static inline void _babl_trc_gamma_2_2_to_linear_buf (const Babl *trc_,
-                                                        const float *in, float *out,
-                                                        int in_gap, int out_gap,
-                                                        int components,
-                                                        int count)
-{
-  int i, c;
-  for (i = 0; i < count; i ++)
-    for (c = 0; c < components; c ++)
-      out[i * out_gap + c] = _babl_trc_gamma_2_2_to_linear (trc_, in[i * in_gap + c]);
-}
-
 
 const Babl *
 babl_trc (const char *name)
@@ -695,9 +548,8 @@ babl_trc_new (const char *name,
   trc.instance.class_type = BABL_TRC;
   trc.instance.id         = 0;
   trc.type = type;
-  trc.gamma = gamma;
-  if (gamma > 0.0001)
-    trc.rgamma = 1.0 / gamma;
+  trc.gamma  = gamma > 0.0    ? gamma       : 0.0;
+  trc.rgamma = gamma > 0.0001 ? 1.0 / gamma : 0.0;
 
   if (n_lut )
   {
@@ -780,6 +632,22 @@ babl_trc_new (const char *name,
       trc_db[i].fun_from_linear = _babl_trc_gamma_from_linear;
       trc_db[i].fun_to_linear_buf = _babl_trc_gamma_to_linear_buf;
       trc_db[i].fun_from_linear_buf = _babl_trc_gamma_from_linear_buf;
+
+      trc_db[i].poly_gamma_to_linear_x0 = POLY_GAMMA_X0;
+      trc_db[i].poly_gamma_to_linear_x1 = POLY_GAMMA_X1;
+      babl_polynomial_approximate_gamma (&trc_db[i].poly_gamma_to_linear,
+                                         trc_db[i].gamma,
+                                         trc_db[i].poly_gamma_to_linear_x0,
+                                         trc_db[i].poly_gamma_to_linear_x1,
+                                         POLY_GAMMA_DEGREE, POLY_GAMMA_SCALE);
+
+      trc_db[i].poly_gamma_from_linear_x0 = POLY_GAMMA_X0;
+      trc_db[i].poly_gamma_from_linear_x1 = POLY_GAMMA_X1;
+      babl_polynomial_approximate_gamma (&trc_db[i].poly_gamma_from_linear,
+                                         trc_db[i].rgamma,
+                                         trc_db[i].poly_gamma_from_linear_x0,
+                                         trc_db[i].poly_gamma_from_linear_x1,
+                                         POLY_GAMMA_DEGREE, POLY_GAMMA_SCALE);
       break;
     case BABL_TRC_FORMULA_SRGB:
       trc_db[i].lut = babl_calloc (sizeof (float), 5);
@@ -790,18 +658,22 @@ babl_trc_new (const char *name,
       }
       trc_db[i].fun_to_linear = _babl_trc_formula_srgb_to_linear;
       trc_db[i].fun_from_linear = _babl_trc_formula_srgb_from_linear;
-      break;
-    case BABL_TRC_GAMMA_2_2:
-      trc_db[i].fun_to_linear = _babl_trc_gamma_2_2_to_linear;
-      trc_db[i].fun_from_linear = _babl_trc_gamma_2_2_from_linear;
-      trc_db[i].fun_from_linear_buf = _babl_trc_gamma_2_2_from_linear_buf;
-      trc_db[i].fun_to_linear_buf = _babl_trc_gamma_2_2_to_linear_buf;
-      break;
-    case BABL_TRC_GAMMA_1_8:
-      trc_db[i].fun_to_linear = _babl_trc_gamma_1_8_to_linear;
-      trc_db[i].fun_from_linear = _babl_trc_gamma_1_8_from_linear;
-      trc_db[i].fun_from_linear_buf = _babl_trc_gamma_1_8_from_linear_buf;
-      trc_db[i].fun_to_linear_buf = _babl_trc_gamma_1_8_to_linear_buf;
+
+      trc_db[i].poly_gamma_to_linear_x0 = lut[4];
+      trc_db[i].poly_gamma_to_linear_x1 = POLY_GAMMA_X1;
+      babl_polynomial_approximate_gamma (&trc_db[i].poly_gamma_to_linear,
+                                         trc_db[i].gamma,
+                                         trc_db[i].poly_gamma_to_linear_x0,
+                                         trc_db[i].poly_gamma_to_linear_x1,
+                                         POLY_GAMMA_DEGREE, POLY_GAMMA_SCALE);
+
+      trc_db[i].poly_gamma_from_linear_x0 = lut[3] * lut[4];
+      trc_db[i].poly_gamma_from_linear_x1 = POLY_GAMMA_X1;
+      babl_polynomial_approximate_gamma (&trc_db[i].poly_gamma_from_linear,
+                                         trc_db[i].rgamma,
+                                         trc_db[i].poly_gamma_from_linear_x0,
+                                         trc_db[i].poly_gamma_from_linear_x1,
+                                         POLY_GAMMA_DEGREE, POLY_GAMMA_SCALE);
       break;
     case BABL_TRC_SRGB:
       trc_db[i].fun_to_linear = _babl_trc_srgb_to_linear;
@@ -860,10 +732,6 @@ babl_trc_gamma (double gamma)
   int i;
   if (fabs (gamma - 1.0) < 0.01)
      return babl_trc_new ("linear", BABL_TRC_LINEAR, 1.0, 0, NULL);
-  if (fabs (gamma - 1.8) < 0.01)
-     return babl_trc_new ("1.8", BABL_TRC_GAMMA_1_8, 1.8, 0, NULL);
-  if (fabs (gamma - 2.2) < 0.01)
-     return babl_trc_new ("2.2", BABL_TRC_GAMMA_2_2, 2.2, 0, NULL);
 
   sprintf (name, "%.6f", gamma);
   for (i = 0; name[i]; i++)
diff --git a/babl/babl-trc.h b/babl/babl-trc.h
index 95020b9..e7e5da5 100644
--- a/babl/babl-trc.h
+++ b/babl/babl-trc.h
@@ -22,13 +22,12 @@
 #include <math.h>
 #include <string.h>
 #include "base/util.h"
+#include "babl-polynomial.h"
 
 BABL_CLASS_DECLARE (trc);
 
 typedef enum {BABL_TRC_LINEAR,
               BABL_TRC_FORMULA_GAMMA,
-              BABL_TRC_GAMMA_1_8,
-              BABL_TRC_GAMMA_2_2,
               BABL_TRC_SRGB,
               BABL_TRC_FORMULA_SRGB,
               BABL_TRC_LUT}
@@ -58,6 +57,12 @@ typedef struct
                                       int out_gap,
                                       int components,
                                       int count);
+  BablPolynomial   poly_gamma_to_linear;
+  float            poly_gamma_to_linear_x0;
+  float            poly_gamma_to_linear_x1;
+  BablPolynomial   poly_gamma_from_linear;
+  float            poly_gamma_from_linear_x0;
+  float            poly_gamma_from_linear_x1;
   float           *lut;
   float           *inv_lut;
   char             name[128];


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]