[babl/wip/icc-cluts: 3/5] babl: implement icc mft2 b2a0 parsing/handling



commit e3d93424a8276d134ae5c23b04ef111f1fd21ade
Author: Øyvind Kolås <pippin gimp org>
Date:   Tue Sep 5 03:37:53 2017 +0200

    babl: implement icc mft2 b2a0 parsing/handling

 babl/babl-fish-reference.c |   45 ++++++++++----
 babl/babl-icc.c            |   43 +++++++-----
 babl/babl-space.c          |   80 ++++++++++++++++++++++-
 babl/babl-space.h          |  151 +++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 277 insertions(+), 42 deletions(-)
---
diff --git a/babl/babl-fish-reference.c b/babl/babl-fish-reference.c
index d97cca3..3e3b24e 100644
--- a/babl/babl-fish-reference.c
+++ b/babl/babl-fish-reference.c
@@ -434,11 +434,12 @@ babl_fish_reference_process (const Babl *babl,
   Babl *source_image;
   Babl *rgba_image;
   Babl *destination_image;
+  BablSpace *destination_space = (void*)&((babl->fish.destination)->format.space->space);
+  BablSpace *source_space = (void*)&((babl->fish.source)->format.space->space);
 
   if ((BABL (babl->fish.source)->format.model ==
        BABL (babl->fish.destination)->format.model) &&
-      (BABL (babl->fish.source)->format.space ==
-       BABL (babl->fish.destination)->format.space)
+       (source_space == destination_space)
       )
     return process_same_model (babl, source, destination, n);
 
@@ -492,17 +493,37 @@ babl_fish_reference_process (const Babl *babl,
     else babl_fatal ("oops");
   }
 
-  if (((babl->fish.source)->format.space !=
-      ((babl->fish.destination)->format.space)))
+  if (source_space != destination_space || 1)
   {
-    double matrix[9];
-    double *rgba = rgba_double_buf;
-    babl_matrix_mul_matrix (
-      (babl->fish.destination)->format.space->space.XYZtoRGB,
-      (babl->fish.source)->format.space->space.RGBtoXYZ,
-      matrix);
-
-    babl_matrix_mul_vector_buf4 (matrix, rgba, rgba, n);
+    // if neither space has luts we use the matrix
+    if (destination_space->b2a0 || source_space->a2b0)
+    {
+      int i;
+
+      double *rgba = rgba_double_buf;
+      for (i = 0; i < n; i++)
+      {
+        double  xyz[4];
+        static int counter = 0;
+  if (counter ++ % 100000 == 0)
+          fprintf (stderr, "!");
+
+        babl_space_to_xyz ((void*)source_space, rgba, xyz);
+        babl_space_from_xyz ((void*)destination_space, xyz, rgba);
+        rgba += 4;
+      }
+    }
+    else
+    {
+      double matrix[9];
+      double *rgba = rgba_double_buf;
+      babl_matrix_mul_matrix (
+        (babl->fish.destination)->format.space->space.XYZtoRGB,
+        (babl->fish.source)->format.space->space.RGBtoXYZ,
+        matrix);
+
+      babl_matrix_mul_vector_buf4 (matrix, rgba, rgba, n);
+    }
   }
 
   {
diff --git a/babl/babl-icc.c b/babl/babl-icc.c
index 32f1066..ae4b50b 100644
--- a/babl/babl-icc.c
+++ b/babl/babl-icc.c
@@ -668,27 +668,27 @@ static char *decode_string (ICC *state, const char *tag, const char *lang, const
   return NULL;
 }
 
-static ICCv2CLUT *load_mft2 (ICC *state, int offset)
+static ICCv2CLUT *load_mft2 (ICC *state, int offset, int size)
 {
   int i, c;
   int o;
   ICCv2CLUT *clut = babl_calloc (sizeof (ICCv2CLUT), 1);
-  clut->clut_size = icc_read (u8,  offset + 10);
+  clut->clut_size[0] = icc_read (u8,  offset + 10);
+  clut->clut_size[1] = icc_read (u8,  offset + 10);
+  clut->clut_size[2] = icc_read (u8,  offset + 10);
   clut->in_table_size = icc_read (u16, offset + 48);
   clut->out_table_size = icc_read (u16, offset + 50);
 
+
   for (i = 0; i < 9; i++)
     clut->matrix[i] = icc_read (s15f16, offset + 12 + i * 4);
 
-  clut->clut = babl_calloc (sizeof (float), 3 * clut->clut_size * clut->clut_size * clut->clut_size);
+  clut->clut = babl_calloc (sizeof (float), 3 * clut->clut_size[0] * clut->clut_size[1] * 
(clut->clut_size[2]+1));
   for (c = 0; c < 3; c++)
     clut->in_table[c] = babl_calloc (sizeof (float), clut->in_table_size);
   for (c = 0; c < 3; c++)
     clut->out_table[c] = babl_calloc (sizeof (float), clut->out_table_size);
 
-  for (i = 0; i < 9; i++)
-    clut->matrix[i] = icc_read (s15f16, offset + 12 + i * 4);
-
   o = 52;
   for (c = 0; c < 3; c++)
     for (i = 0; i < clut->in_table_size; i++)
@@ -696,7 +696,7 @@ static ICCv2CLUT *load_mft2 (ICC *state, int offset)
       clut->in_table[c][i] = icc_read (u16, offset + o) / 65535.0;
       o+=2;
     }
-  for (i = 0; i < 3 * clut->clut_size * clut->clut_size * clut->clut_size; i++)
+  for (i = 0; i < 3 * clut->clut_size[0] * clut->clut_size[1] * clut->clut_size[2]; i++)
     {
       clut->clut[i] = icc_read (u16, offset + o) / 65535.0;
       o+=2;
@@ -715,22 +715,29 @@ static ICCv2CLUT *load_mft1 (ICC *state, int offset)
   int i, c;
   int o;
   ICCv2CLUT *clut = babl_calloc (sizeof (ICCv2CLUT), 1);
-  clut->clut_size = icc_read (u8,  offset + 10);
+
+  clut->clut_size[0] = icc_read (u8,  offset + 10);
+  clut->clut_size[1] = icc_read (u8,  offset + 10);
+  clut->clut_size[2] = icc_read (u8,  offset + 10);
   clut->in_table_size = 256;
   clut->out_table_size = 256;
 
-  for (i = 0; i < 9; i++)
-    clut->matrix[i] = icc_read (s15f16, offset + 12 + i * 4);
-
-  clut->clut = babl_calloc (sizeof (float), 3 * clut->clut_size * clut->clut_size * clut->clut_size);
+  clut->matrix[0] = icc_read (s15f16, offset + 12 + 0 * 4);
+  clut->matrix[1] = icc_read (s15f16, offset + 12 + 3 * 4);
+  clut->matrix[2] = icc_read (s15f16, offset + 12 + 6 * 4);
+  clut->matrix[3] = icc_read (s15f16, offset + 12 + 1 * 4);
+  clut->matrix[4] = icc_read (s15f16, offset + 12 + 4 * 4);
+  clut->matrix[5] = icc_read (s15f16, offset + 12 + 7 * 4);
+  clut->matrix[6] = icc_read (s15f16, offset + 12 + 2 * 4);
+  clut->matrix[7] = icc_read (s15f16, offset + 12 + 5 * 4);
+  clut->matrix[8] = icc_read (s15f16, offset + 12 + 8 * 4);
+
+  clut->clut = babl_calloc (sizeof (float), 3 * clut->clut_size[0] * clut->clut_size[1] * 
(clut->clut_size[2]+1));
   for (c = 0; c < 3; c++)
     clut->in_table[c] = babl_calloc (sizeof (float), clut->in_table_size);
   for (c = 0; c < 3; c++)
     clut->out_table[c] = babl_calloc (sizeof (float), clut->out_table_size);
 
-  for (i = 0; i < 9; i++)
-    clut->matrix[i] = icc_read (s15f16, offset + 12 + i * 4);
-
   o = 52;
   for (c = 0; c < 3; c++)
     for (i = 0; i < clut->in_table_size; i++)
@@ -738,7 +745,7 @@ static ICCv2CLUT *load_mft1 (ICC *state, int offset)
       clut->in_table[c][i] = icc_read (u8, offset + o) / 255.0;
       o++;
     }
-  for (i = 0; i < 3 * clut->clut_size * clut->clut_size * clut->clut_size; i++)
+  for (i = 0; i < 3 * clut->clut_size[0] * clut->clut_size[1] * clut->clut_size[2]; i++)
     {
       clut->clut[i] = icc_read (u8, offset + o) / 255.0;
       o++;
@@ -827,7 +834,7 @@ babl_space_from_icc (const char   *icc_data,
     if (icc_tag (state, "A2B0", &offset, &element_size))
     {
       if (!strcmp (state->data + offset, "mft2"))
-        a2b0 = load_mft2 (state, offset);
+        a2b0 = load_mft2 (state, offset, element_size);
       else if (!strcmp (state->data + offset, "mft1"))
         a2b0 = load_mft1 (state, offset);
     }
@@ -838,7 +845,7 @@ babl_space_from_icc (const char   *icc_data,
     if (icc_tag (state, "B2A0", &offset, &element_size))
     {
       if (!strcmp (state->data + offset, "mft2"))
-        b2a0 = load_mft2 (state, offset);
+        b2a0 = load_mft2 (state, offset, element_size);
       else if (!strcmp (state->data + offset, "mft1"))
         b2a0 = load_mft1 (state, offset);
     }
diff --git a/babl/babl-space.c b/babl/babl-space.c
index 6966aba..9d4324e 100644
--- a/babl/babl-space.c
+++ b/babl/babl-space.c
@@ -474,8 +474,6 @@ static void prep_conversion (const Babl *babl)
 } while(0)
 
 
-
-
 static inline void
 universal_nonlinear_rgb_converter (const Babl *conversion,unsigned char *src_char, unsigned char *dst_char, 
long samples)
 {
@@ -742,11 +740,86 @@ universal_nonlinear_rgb_linear_converter_sse2 (const Babl *conversion,unsigned c
 }
 #endif
 
+static inline long
+universal_generic_rgba_converter (const Babl *conversion,unsigned char *src_char, unsigned char *dst_char, 
long samples)
+{
+  const Babl *source_space = babl_conversion_get_source_space (conversion);
+  const Babl *destination_space = babl_conversion_get_destination_space (conversion);
+  float *rgba_in = (void*)src_char;
+  float *rgba_out = (void*)dst_char;
+
+  int i;
+  for (i = 0; i < samples; i++)
+  {
+     double rgba[4] = {rgba_in[0], rgba_in[1], rgba_in[2]};
+     babl_space_to_xyz (source_space,
+                        rgba, rgba);
+     babl_space_from_xyz (destination_space,
+                          rgba, rgba);
+     rgba_out[0] = rgba[0];
+     rgba_out[1] = rgba[1];
+     rgba_out[2] = rgba[2];
+     rgba_out[3] = rgba_in[3];
+     rgba_in += 4;
+     rgba_out += 4;
+     {
+        static int counter = 0;
+  if (counter ++ % 100000 == 0)
+          fprintf (stderr, "%%");
+  }
+  }
+  return samples;
+}
+
+static inline long
+universal_generic_rgb_converter (const Babl *conversion,unsigned char *src_char, unsigned char *dst_char, 
long samples)
+{
+  const Babl *source_space = babl_conversion_get_source_space (conversion);
+  const Babl *destination_space = babl_conversion_get_destination_space (conversion);
+  float *rgba_in = (void*)src_char;
+  float *rgba_out = (void*)dst_char;
+
+  int i;
+  for (i = 0; i < samples; i++)
+  {
+     double rgba[4] = {rgba_in[0], rgba_in[1], rgba_in[2]};
+     babl_space_to_xyz (source_space, rgba, rgba);
+     babl_space_from_xyz (destination_space, rgba, rgba);
+     rgba_out[0] = rgba[0];
+     rgba_out[1] = rgba[1];
+     rgba_out[2] = rgba[2];
+     rgba_in += 3;
+     rgba_out += 3;
+
+
+     {
+        static int counter = 0;
+  if (counter ++ % 100000 == 0)
+          fprintf (stderr, ":");
+  }
+  }
+  return samples;
+}
 
 static int
 add_rgb_adapter (Babl *babl,
-                 void *space)
+                 void *data)
 {
+  Babl *space = data;
+
+  if (space->space.a2b0 || babl->space.a2b0)
+  {
+    prep_conversion(babl_conversion_new(babl_format_with_space("RGBA float", (void*)space),
+                    babl_format_with_space("RGBA float", babl),
+                    "linear", universal_generic_rgba_converter,
+                    NULL));
+    prep_conversion(babl_conversion_new(babl_format_with_space("RGB float", (void*)space),
+                    babl_format_with_space("RGB float", babl),
+                    "linear", universal_generic_rgb_converter,
+                    NULL));
+    return 0;
+  }
+
   if (babl != space)
   {
 
@@ -879,3 +952,4 @@ const Babl *babl_space_match_trc_matrix (const Babl *trc_red,
   }
   return NULL;
 }
+
diff --git a/babl/babl-space.h b/babl/babl-space.h
index a5c2e08..4b4ae38 100644
--- a/babl/babl-space.h
+++ b/babl/babl-space.h
@@ -29,7 +29,7 @@ BABL_CLASS_DECLARE (space);
 typedef struct
 {
   float  *clut;
-  int     clut_size;
+  int     clut_size[3];
   int     in_table_size;
   int     out_table_size;
   float   matrix[9];
@@ -37,6 +37,7 @@ typedef struct
   float  *out_table[3];
 } ICCv2CLUT;
 
+
 typedef struct
 {
   BablInstance     instance;
@@ -78,28 +79,160 @@ typedef struct
 
 } BablSpace;
 
+
+static inline float do_lut (float *lut, int lut_size, float value)
+{
+  int entry;
+  float diff;
+  entry = value * (lut_size-1);
+  diff = ( (value * (lut_size-1)) - entry);
+  if (entry >= lut_size) entry = lut_size - 1;
+  else if (entry < 0) entry = 0;
+
+  if (diff > 0.0 && entry < lut_size - 1)
+  {
+    return lut[entry] * (1.0 - diff) + lut[entry+1] * diff;
+  }
+  else
+  {
+    return lut[entry];
+  }
+}
+
+static inline void clut_interpol (ICCv2CLUT *clut, const double *ind, double *outd)
+{
+  float val[3] = {ind[0], ind[1], ind[2]};
+  int   entry[3];
+  float diff[3];
+  int *dim = clut->clut_size;
+  int c;
+
+  babl_matrix_mul_vectorff (clut->matrix, val, val);
+
+  for (c = 0; c < 3; c ++)
+  {
+     val[c] = do_lut (clut->in_table[c], clut->in_table_size, val[c]);
+  }
+
+  for (c = 0; c < 3; c++)
+  {
+     entry[c] = val[c] * (dim[c]-1);
+     diff[c] = ((val[c] * (dim[c]-1)) - entry[c]);
+
+     if (entry[c] >= dim[c] - 1)
+     {
+       entry[c] = dim[c] - 1;
+       diff[c] = 0.0;
+     }
+     else if (entry[c] <= 0.0001)
+     {
+       entry[c] = 0;
+       diff[c] = 0.0;
+     }
+  }
+
+  // needs rework for non-same sized acceses
+#define IDX(a,b,c,comp) (((a) * dim[0] * dim[1] + (b) * dim[0] + (c)) * 3 + comp)
+
+  for (c = 0; c < 3; c ++)
+  {
+#if 1
+     val[c] =
+        ((clut->clut[IDX(entry[0],  entry[1],   entry[2],c  )] * (1.0 - diff[0]) +
+         clut->clut[IDX(entry[0]+1, entry[1],   entry[2],c  )] * (diff[0])) * (1.0 - diff[1]) +
+
+        (clut->clut[IDX(entry[0],   entry[1]+1, entry[2],c  )] * (1.0 - diff[0]) +
+         clut->clut[IDX(entry[0]+1, entry[1]+1, entry[2],c  )] * (diff[0])) * diff[1]) *
+                        (1.0-diff[2]) +
+
+        ((clut->clut[IDX(entry[0],  entry[1],   entry[2]+1,c)] * (1.0 - diff[0]) +
+         clut->clut[IDX(entry[0]+1, entry[1],   entry[2]+1,c)] * (diff[0])) * (1.0 - diff[1]) +
+
+        (clut->clut[IDX(entry[0],   entry[1]+1, entry[2]+1,c)] * (1.0 - diff[0]) +
+         clut->clut[IDX(entry[0]+1, entry[1]+1, entry[2]+1,c)] * (diff[0])) * diff[1]) * diff[2];
+#else
+     val[c] = clut->clut[IDX(entry[0], entry[1], entry[2],c)];
+#endif
+  }
+  for (c = 0; c < 3; c ++)
+    val[c] = do_lut (clut->out_table[c], clut->out_table_size, val[c]);
+  for (c = 0; c < 3; c ++)
+     outd[c] = val[c];
+}
+
+
 static inline void babl_space_to_xyzf (const Babl *space, const float *rgb, float *xyz)
 {
   BablSpace *space_ = (void*)space;
-  babl_matrix_mul_vectorff (space_->RGBtoXYZf, rgb, xyz);
+  double rgbmat[3] = {rgb[0], rgb[1], rgb[2]};
+  double xyzmat[3];
+  if (space_->a2b0)
+  {
+    int c;
+    for (c = 0; c < 3; c++)
+      rgbmat[c] = babl_trc_from_linear (space_->trc[c], rgbmat[c]);
+    clut_interpol (space_->a2b0, rgbmat, xyzmat);
+  }
+  else
+  {
+    babl_matrix_mul_vector (space_->RGBtoXYZ, rgbmat, xyzmat);
+  }
+  xyz[0] = xyzmat[0];
+  xyz[1] = xyzmat[1];
+  xyz[2] = xyzmat[2];
 }
 
+
 static inline void babl_space_from_xyzf (const Babl *space, const float *xyz, float *rgb)
 {
   BablSpace *space_ = (void*)space;
-  babl_matrix_mul_vectorff (space_->XYZtoRGBf, xyz, rgb);
+  double xyzmat[3] = {xyz[0], xyz[1], xyz[2]};
+  double rgbmat[3];
+  if (space_->b2a0)
+  {
+    int c;
+    clut_interpol (space_->b2a0, xyzmat, rgbmat);
+    for (c = 0; c < 3; c++)
+      rgbmat[c] = babl_trc_to_linear (space_->trc[c], rgbmat[c]);
+  }
+  else
+  {
+    babl_matrix_mul_vector (space_->XYZtoRGB, xyzmat, rgbmat);
+  }
+  rgb[0] = rgbmat[0];
+  rgb[1] = rgbmat[1];
+  rgb[2] = rgbmat[2];
 }
 
-static inline void _babl_space_to_xyz (const Babl *space, const double *rgb, double *xyz)
+
+static inline void _babl_space_to_xyz (const Babl *space_, const double *rgb, double *xyz)
 {
-  BablSpace *space_ = (void*)space;
-  babl_matrix_mul_vector (space_->RGBtoXYZ, rgb, xyz);
+  BablSpace *space = (void*)space_;
+  if (space->a2b0)
+  {
+    int c;
+    for (c = 0; c < 3; c++)
+      xyz[c] = babl_trc_from_linear (space->trc[c], rgb[c]);
+    clut_interpol (space->a2b0, xyz, xyz);
+  }
+  else
+    babl_matrix_mul_vector (space->RGBtoXYZ, rgb, xyz);
 }
 
-static inline void _babl_space_from_xyz (const Babl *space, const double *xyz, double *rgb)
+static inline void _babl_space_from_xyz (const Babl *space_, const double *xyz, double *rgb)
 {
-  BablSpace *space_ = (void*)space;
-  babl_matrix_mul_vector (space_->XYZtoRGB, xyz, rgb);
+  BablSpace *space = (void*)space_;
+  if (space->b2a0)
+  {
+    clut_interpol (space->b2a0, xyz, rgb);
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+        rgb[c] = babl_trc_to_linear (space->trc[c], rgb[c]);
+    }
+  }
+  else
+    babl_matrix_mul_vector (space->XYZtoRGB, xyz, rgb);
 }
 
 void


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