[babl] babl: add parametric handling for sRGB style TRCs (icc V4)
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [babl] babl: add parametric handling for sRGB style TRCs (icc V4)
- Date: Sat, 2 Sep 2017 15:10:36 +0000 (UTC)
commit 01d6e09e590d5537e1d66d2e4e2e68e534b0db43
Author: Øyvind Kolås <pippin gimp org>
Date: Sat Sep 2 17:09:20 2017 +0200
babl: add parametric handling for sRGB style TRCs (icc V4)
babl/babl-icc.c | 100 +++++++++++++++++++++++++++++++++-----------------
babl/babl-internal.h | 2 +
babl/babl-trc.c | 77 ++++++++++++++++++++++++++++++++++----
babl/babl-trc.h | 3 +-
4 files changed, 139 insertions(+), 43 deletions(-)
---
diff --git a/babl/babl-icc.c b/babl/babl-icc.c
index 5ae66bc..debbc69 100644
--- a/babl/babl-icc.c
+++ b/babl/babl-icc.c
@@ -315,22 +315,45 @@ static const Babl *babl_trc_from_icc (ICC *state, int offset,
g = icc_read (s15f16, offset + 12 + 2 * 0);
return babl_trc_gamma (g);
break;
-
case 3:
-#if 0
- float a,b,c,d,e,f;
- g = icc_read (s15f16, offset + 12 + 2 * 0);
- a = icc_read (s15f16, offset + 12 + 2 * 1);
- b = icc_read (s15f16, offset + 12 + 2 * 2);
- c = icc_read (s15f16, offset + 12 + 2 * 3);
- d = icc_read (s15f16, offset + 12 + 2 * 4);
- e = icc_read (s15f16, offset + 12 + 2 * 5);
- f = icc_read (s15f16, offset + 12 + 2 * 6);
-#endif
- return babl_trc ("sRGB"); // XXX: not true... and I suspect the CIE L* curve might be
expressed as this,
- // formula as well, depending on arguments.
+ {
+ float a,b,c,d;
+ g = icc_read (s15f16, offset + 12 + 2 * 0);
+ a = icc_read (s15f16, offset + 12 + 2 * 1);
+ b = icc_read (s15f16, offset + 12 + 2 * 2);
+ c = icc_read (s15f16, offset + 12 + 2 * 3);
+ d = icc_read (s15f16, offset + 12 + 2 * 4);
+ //fprintf (stderr, "%f %f %f %f %f\n", g, a, b, c, d);
+ if (fabs (g - 2.40) < 0.01 &&
+ fabs (a - 26214) < 0.01 &&
+ fabs (b - 0.947875) < 0.01 &&
+ fabs (c - (-3417)) < 0.01)
+ return babl_trc ("sRGB");
+ else
+ return babl_trc_formula_srgb (g, a, b, c, d);
+ }
+ break;
+ case 4:
+ {
+ float a,b,c,d,e,f;
+ g = icc_read (s15f16, offset + 12 + 2 * 0);
+ a = icc_read (s15f16, offset + 12 + 2 * 1);
+ b = icc_read (s15f16, offset + 12 + 2 * 2);
+ c = icc_read (s15f16, offset + 12 + 2 * 3);
+ d = icc_read (s15f16, offset + 12 + 2 * 4);
+ e = icc_read (s15f16, offset + 12 + 2 * 5);
+ f = icc_read (s15f16, offset + 12 + 2 * 6);
+ fprintf (stderr, "%f %f %f %f %f %f %f\n",
+ g, a, b, c, d, e, f);
+ {
+ fprintf (stdout, "unhandled parametric sRGB formula TRC type %i\n", function_type);
+ *error = "unhandled sRGB formula like TRC";
+ return babl_trc_gamma (2.2);
+ }
+ }
break;
default:
+ *error = "unhandled parametric TRC";
fprintf (stdout, "unhandled parametric TRC type %i\n", function_type);
return babl_trc_gamma (2.2);
break;
@@ -399,14 +422,42 @@ switch (trc->type)
icc_write (u32, state->o + 4, 0);
icc_write (u32, state->o + 8, 0);
break;
- case BABL_TRC_GAMMA:
+ case BABL_TRC_FORMULA_GAMMA:
icc_allocate_tag (state, name, 14);
icc_write (sign, state->o, "curv");
icc_write (u32, state->o + 4, 0);
icc_write (u32, state->o + 8, 1);
icc_write (u8f8, state->o + 12, trc->gamma);
break;
+ case BABL_TRC_GAMMA_1_8:
+ icc_allocate_tag (state, name, 14);
+ icc_write (sign, state->o, "curv");
+ icc_write (u32, state->o + 4, 0);
+ icc_write (u32, state->o + 8, 1);
+ icc_write (u8f8, state->o + 12, 1.8);
+ break;
+ 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);
+ icc_write (u32, state->o + 8, 1);
+ icc_write (u8f8, state->o + 12, 2.2);
+ break;
+ case BABL_TRC_LUT:
+ icc_allocate_tag (state, name, 13 + trc->lut_size * 2);
+ icc_write (sign, state->o, "curv");
+ icc_write (u32, state->o + 4, 0);
+ icc_write (u32, state->o + 8, trc->lut_size);
+ {
+ int j;
+ for (j = 0; j < trc->lut_size; j ++)
+ icc_write (u16, state->o + 12 + j * 2, (int)(trc->lut[j]*65535.5f));
+ }
+ break;
+ // this is the case catching things not directly representable in v2
case BABL_TRC_SRGB:
+ case BABL_TRC_FORMULA_SRGB:
+// default:
{
int lut_size = 512;
icc_allocate_tag (state, name, 13 + lut_size * 2);
@@ -417,28 +468,9 @@ switch (trc->type)
int j;
for (j = 0; j < lut_size; j ++)
icc_write (u16, state->o + 12 + j * 2,
- gamma_2_2_to_linear (j / (lut_size-1.0)) * 65535.5);
+ babl_trc_to_linear ((void*)trc, j / (lut_size-1.0)) * 65535.5);
}
}
- break;
- case BABL_TRC_LUT:
- icc_allocate_tag (state, name, 13 + trc->lut_size * 2);
- icc_write (sign, state->o, "curv");
- icc_write (u32, state->o + 4, 0);
- icc_write (u32, state->o + 8, trc->lut_size);
- {
- int j;
- for (j = 0; j < trc->lut_size; j ++)
- icc_write (u16, state->o + 12 + j * 2, (int)(trc->lut[j]*65535.5f));
- }
- break;
- default:
- icc_allocate_tag (state, name, 14);
- icc_write (sign, state->o, "curv");
- icc_write (u32, state->o + 4, 0);
- icc_write (u32, state->o + 8, 1);
- icc_write (u8f8, state->o + 12, trc->gamma);
- break;
}
}
diff --git a/babl/babl-internal.h b/babl/babl-internal.h
index 440f7e8..c7c87cf 100644
--- a/babl/babl-internal.h
+++ b/babl/babl-internal.h
@@ -362,5 +362,7 @@ int babl_list_destroy (void *data);
const char *
babl_conversion_create_name (Babl *source, Babl *destination, int is_reference);
void _babl_space_add_universal_rgb (const Babl *space);
+const Babl *
+babl_trc_formula_srgb (double gamma, double a, double b, double c, double d);
#endif
diff --git a/babl/babl-trc.c b/babl/babl-trc.c
index b9f1c49..4aacdef 100644
--- a/babl/babl-trc.c
+++ b/babl/babl-trc.c
@@ -343,12 +343,6 @@ static inline float babl_powf (float x, float y)
return expf (y * logf (x));
}
-static inline float _babl_trc_gamma_to_linear (const Babl *trc_, float value)
-{
- BablTRC *trc = (void*)trc_;
- 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)
{
@@ -376,6 +370,48 @@ static inline float _babl_trc_gamma_from_linear (const Babl *trc_, float value)
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);
+}
+
+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);
+ v = (v-b)/a;
+ return v;
+ }
+ return x / c;
+}
+
+static inline float _babl_trc_formula_srgb_to_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 >= d)
+ {
+ return babl_powf (a * x + b, g);
+ }
+ 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)
@@ -691,12 +727,22 @@ babl_trc_new (const char *name,
trc_db[i].fun_from_linear_buf = _babl_trc_linear_buf;
trc_db[i].fun_to_linear_buf = _babl_trc_linear_buf;
break;
- case BABL_TRC_GAMMA:
+ case BABL_TRC_FORMULA_GAMMA:
trc_db[i].fun_to_linear = _babl_trc_gamma_to_linear;
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;
break;
+ case BABL_TRC_FORMULA_SRGB:
+ trc_db[i].lut = babl_calloc (sizeof (float), 5);
+ {
+ int j;
+ for (j = 0; j < 5; j++)
+ trc_db[i].lut[j] = lut[j];
+ }
+ 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;
@@ -739,6 +785,21 @@ babl_trc_class_for_each (BablEachFunction each_fun,
}
const Babl *
+babl_trc_formula_srgb (double gamma, double a, double b, double c, double d)
+{
+ char name[32];
+ int i;
+ float params[5]={gamma, a, b, c, d};
+
+ sprintf (name, "%.6f %.6f %.4f %.4f %.4f", gamma, a, b, c, d);
+ for (i = 0; name[i]; i++)
+ if (name[i] == ',') name[i] = '.';
+ while (name[strlen(name)-1]=='0')
+ name[strlen(name)-1]='\0';
+ return babl_trc_new (name, BABL_TRC_FORMULA_SRGB, gamma, 0, params);
+}
+
+const Babl *
babl_trc_gamma (double gamma)
{
char name[32];
@@ -755,7 +816,7 @@ babl_trc_gamma (double gamma)
if (name[i] == ',') name[i] = '.';
while (name[strlen(name)-1]=='0')
name[strlen(name)-1]='\0';
- return babl_trc_new (name, BABL_TRC_GAMMA, gamma, 0, NULL);
+ return babl_trc_new (name, BABL_TRC_FORMULA_GAMMA, gamma, 0, NULL);
}
void
diff --git a/babl/babl-trc.h b/babl/babl-trc.h
index 0b7fb70..95020b9 100644
--- a/babl/babl-trc.h
+++ b/babl/babl-trc.h
@@ -26,10 +26,11 @@
BABL_CLASS_DECLARE (trc);
typedef enum {BABL_TRC_LINEAR,
- BABL_TRC_GAMMA,
+ BABL_TRC_FORMULA_GAMMA,
BABL_TRC_GAMMA_1_8,
BABL_TRC_GAMMA_2_2,
BABL_TRC_SRGB,
+ BABL_TRC_FORMULA_SRGB,
BABL_TRC_LUT}
BablTRCType;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]