From f25c510ae26866b2a7261428b373e38ffaa8dda5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Fri, 7 Aug 2020 23:12:15 +0200 Subject: [PATCH] babl: code handling ICC v4, CIE TRC formulas --- babl/babl-icc.c | 24 ++++++++++--- babl/babl-internal.h | 2 ++ babl/babl-trc.c | 84 ++++++++++++++++++++++++++++++++++++++++++++ babl/babl-trc.h | 3 +- 4 files changed, 108 insertions(+), 5 deletions(-) diff --git a/babl/babl-icc.c b/babl/babl-icc.c index aa5a386..7d1fd67 100644 --- a/babl/babl-icc.c +++ b/babl/babl-icc.c @@ -384,9 +384,27 @@ babl_trc_from_icc (ICC *state, g = icc_read (s15f16, offset + 12 + 4 * 0); return babl_trc_gamma (g); break; + case 1: + { + float a,b,c; + g = icc_read (s15f16, offset + 12 + 4 * 0); + a = icc_read (s15f16, offset + 12 + 4 * 1); + b = icc_read (s15f16, offset + 12 + 4 * 2); + c = 0; + return babl_trc_formula_cie (g, a, b, c); + } + case 2: + { + float a,b,c; + g = icc_read (s15f16, offset + 12 + 4 * 0); + a = icc_read (s15f16, offset + 12 + 4 * 1); + b = icc_read (s15f16, offset + 12 + 4 * 2); + c = icc_read (s15f16, offset + 12 + 4 * 3); + return babl_trc_formula_cie (g, a, b, c); + } case 3: { - float a,b,c,d, e, f; + float a,b,c,d,e,f; g = icc_read (s15f16, offset + 12 + 4 * 0); a = icc_read (s15f16, offset + 12 + 4 * 1); b = icc_read (s15f16, offset + 12 + 4 * 2); @@ -408,8 +426,6 @@ babl_trc_from_icc (ICC *state, f = icc_read (s15f16, offset + 12 + 4 * 6); return babl_trc_formula_srgb (g, a, b, c, d, e, f); } - case 1: // NYI - case 2: // NYI - can share code, like srgb formulas default: *error = "unhandled parametric TRC"; fprintf (stderr, "unhandled parametric TRC type %i\n", function_type); @@ -534,6 +550,7 @@ switch (trc->type) break; } case BABL_TRC_FORMULA_SRGB: + case BABL_TRC_FORMULA_CIE: { int lut_size = 512; if (flags == BABL_ICC_COMPACT_TRC_LUT) @@ -671,7 +688,6 @@ babl_space_to_icc_rgb (const Babl *babl, icc_write (u8, state->o + 12 + i, description[i]); } - icc_write (u32, 0, state->no + 0); length = state->no + 0; } diff --git a/babl/babl-internal.h b/babl/babl-internal.h index 1efdb0f..56e95e4 100644 --- a/babl/babl-internal.h +++ b/babl/babl-internal.h @@ -386,6 +386,8 @@ babl_conversion_create_name (Babl *source, Babl *destination, int type, 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, double e, double f); +const Babl * +babl_trc_formula_cie (double gamma, double a, double b, double c); const Babl *babl_space_match_trc_matrix (const Babl *trc_red, diff --git a/babl/babl-trc.c b/babl/babl-trc.c index b1ba8a8..d8a69dd 100644 --- a/babl/babl-trc.c +++ b/babl/babl-trc.c @@ -200,6 +200,44 @@ _babl_trc_formula_srgb_to_linear (const Babl *trc_, } return c * x + f; } +static inline float +_babl_trc_formula_cie_from_linear (const Babl *trc_, + float value) +{ + BablTRC *trc = (void*)trc_; + float x= value; + float a = trc->lut[1]; + float b = trc->lut[2]; + float c = trc->lut[3]; + + if (x > c) + { + float v = _babl_trc_gamma_from_linear ((Babl *) trc, x - c); + v = (v-b)/a; + if (v < 0.0 || v >= 0.0) + return v; + } + return 0.0; +} + +static inline float +_babl_trc_formula_cie_to_linear (const Babl *trc_, + float value) +{ + BablTRC *trc = (void*)trc_; + float x= value; + float a = trc->lut[1]; + float b = trc->lut[2]; + float c = trc->lut[3]; + + if (x >= -b / a) + { + return _babl_trc_gamma_to_linear ((Babl *) trc, a * x + b) + c; + } + return c; +} + + static inline float _babl_trc_srgb_to_linear (const Babl *trc_, @@ -421,6 +459,33 @@ babl_trc_new (const char *name, trc_db[i].poly_gamma_from_linear_x1, POLY_GAMMA_DEGREE, POLY_GAMMA_SCALE); break; + case BABL_TRC_FORMULA_CIE: + trc_db[i].lut = babl_calloc (sizeof (float), 4); + { + int j; + for (j = 0; j < 4; j++) + trc_db[i].lut[j] = lut[j]; + } + trc_db[i].fun_to_linear = _babl_trc_formula_cie_to_linear; + trc_db[i].fun_from_linear = _babl_trc_formula_cie_from_linear; + + 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_FORMULA_SRGB: trc_db[i].lut = babl_calloc (sizeof (float), 7); { @@ -510,6 +575,25 @@ babl_trc_formula_srgb (double g, return babl_trc_new (name, BABL_TRC_FORMULA_SRGB, g, 0, params); } +const Babl * +babl_trc_formula_cie (double g, + double a, + double b, + double c) +{ + char name[128]; + int i; + float params[4]={g, a, b, c}; + + snprintf (name, sizeof (name), "%.6f %.6f %.4f %.4f", g, a, b, c); + 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_CIE, g, 0, params); +} + + const Babl * babl_trc_gamma (double gamma) { diff --git a/babl/babl-trc.h b/babl/babl-trc.h index 380a736..cfe742c 100644 --- a/babl/babl-trc.h +++ b/babl/babl-trc.h @@ -30,7 +30,8 @@ typedef enum {BABL_TRC_LINEAR, BABL_TRC_FORMULA_GAMMA, BABL_TRC_SRGB, BABL_TRC_FORMULA_SRGB, - BABL_TRC_LUT} + BABL_TRC_LUT, + BABL_TRC_FORMULA_CIE} BablTRCType; typedef struct -- 2.30.2