babl-space: add universal convertors between linear and nonlinear
authorØyvind Kolås <pippin@gimp.org>
Mon, 22 Jul 2019 01:22:11 +0000 (03:22 +0200)
committerØyvind Kolås <pippin@gimp.org>
Mon, 22 Jul 2019 01:36:02 +0000 (03:36 +0200)
Register conversions for all space pairs between "R'G'B'A float" and
"RGBA float" and vice versa, both SSE2 and non SIMD versions.

babl/babl-space.c
babl/babl-space.h
docs/Makefile.am
docs/index-static.html.in
docs/meson.build
tools/babl-verify.c

index 943da85205660e1b6a46a7e4ff5d1a3baebfd062..67e85357190d86992999a930a3ffa77c84f938b2 100644 (file)
@@ -728,6 +728,23 @@ universal_nonlinear_rgb_linear_converter (const Babl    *conversion,
   babl_matrix_mul_vectorff_buf4 (matrixf, rgba_out, rgba_out, samples);
 }
 
+static inline void
+universal_linear_rgb_nonlinear_converter (const Babl    *conversion,
+                                          unsigned char *src_char,
+                                          unsigned char *dst_char,
+                                          long           samples,
+                                          void          *data)
+{
+  const Babl *destination_space = conversion->conversion.destination->format.space;
+  float * matrixf = data;
+  float *rgba_in = (void*)src_char;
+  float *rgba_out = (void*)dst_char;
+
+  babl_matrix_mul_vectorff_buf4 (matrixf, rgba_in, rgba_out, samples);
+
+  TRC_OUT(rgba_out, rgba_out);
+}
+
 static inline void
 universal_nonlinear_rgba_u8_converter (const Babl    *conversion,
                                        unsigned char *src_char,
@@ -1007,6 +1024,24 @@ universal_nonlinear_rgb_linear_converter_sse2 (const Babl    *conversion,
 
   babl_matrix_mul_vectorff_buf4_sse2 (matrixf, rgba_out, rgba_out, samples);
 }
+
+
+static inline void
+universal_linear_rgb_nonlinear_converter_sse2 (const Babl    *conversion,
+                                               unsigned char *src_char,
+                                               unsigned char *dst_char,
+                                               long           samples,
+                                               void          *data)
+{
+  const Babl *destination_space = conversion->conversion.destination->format.space;
+  float * matrixf = data;
+  float *rgba_in = (void*)src_char;
+  float *rgba_out = (void*)dst_char;
+
+  babl_matrix_mul_vectorff_buf4_sse2 (matrixf, rgba_in, rgba_out, samples);
+
+  TRC_OUT(rgba_out, rgba_out);
+}
 #endif
 
 
@@ -1021,6 +1056,8 @@ add_rgb_adapter (Babl *babl,
     if ((babl_cpu_accel_get_support () & BABL_CPU_ACCEL_X86_SSE) &&
         (babl_cpu_accel_get_support () & BABL_CPU_ACCEL_X86_SSE2))
     {
+
+
        prep_conversion(babl_conversion_new(
                        babl_format_with_space("RGBA float", space),
                        babl_format_with_space("RGBA float", babl),
@@ -1041,6 +1078,29 @@ add_rgb_adapter (Babl *babl,
                        babl_format_with_space("R'G'B'A float", space),
                        "linear", universal_nonlinear_rgba_converter_sse2,
                        NULL));
+
+       prep_conversion(babl_conversion_new(
+                       babl_format_with_space("R'G'B'A float", space),
+                       babl_format_with_space("RGBA float", babl),
+                       "linear", universal_nonlinear_rgb_linear_converter_sse2,
+                       NULL));
+       prep_conversion(babl_conversion_new(
+                       babl_format_with_space("R'G'B'A float", babl),
+                       babl_format_with_space("RGBA float", space),
+                       "linear", universal_nonlinear_rgb_linear_converter_sse2,
+                       NULL));
+
+       prep_conversion(babl_conversion_new(
+                       babl_format_with_space("RGBA float", babl),
+                       babl_format_with_space("R'G'B'A float", space),
+                       "linear", universal_linear_rgb_nonlinear_converter_sse2,
+                       NULL));
+       prep_conversion(babl_conversion_new(
+                       babl_format_with_space("RGBA float", space),
+                       babl_format_with_space("R'G'B'A float", babl),
+                       "linear", universal_linear_rgb_nonlinear_converter_sse2,
+                       NULL));
+
        prep_conversion(babl_conversion_new(
                        babl_format_with_space("R'G'B'A u8", space),
                        babl_format_with_space("R'G'B'A u8", babl),
@@ -1076,6 +1136,7 @@ add_rgb_adapter (Babl *babl,
                        babl_format_with_space("RGBA float", space),
                        "linear", universal_rgba_converter,
                        NULL));
+
        prep_conversion(babl_conversion_new(
                        babl_format_with_space("R'G'B'A float", space),
                        babl_format_with_space("R'G'B'A float", babl),
@@ -1086,6 +1147,18 @@ add_rgb_adapter (Babl *babl,
                        babl_format_with_space("R'G'B'A float", space),
                        "linear", universal_nonlinear_rgba_converter,
                        NULL));
+
+       prep_conversion(babl_conversion_new(
+                       babl_format_with_space("R'G'B'A float", space),
+                       babl_format_with_space("RGBA float", babl),
+                       "linear", universal_nonlinear_rgb_linear_converter_sse2,
+                       NULL));
+       prep_conversion(babl_conversion_new(
+                       babl_format_with_space("R'G'B'A float", babl),
+                       babl_format_with_space("RGBA float", space),
+                       "linear", universal_nonlinear_rgb_linear_converter_sse2,
+                       NULL));
+
        prep_conversion(babl_conversion_new(
                        babl_format_with_space("R'G'B'A u8", space),
                        babl_format_with_space("R'G'B'A u8", babl),
@@ -1107,6 +1180,17 @@ add_rgb_adapter (Babl *babl,
                        babl_format_with_space("R'G'B' u8", space),
                        "linear", universal_nonlinear_rgb_u8_converter,
                        NULL));
+
+       prep_conversion(babl_conversion_new(
+                       babl_format_with_space("RGBA float", babl),
+                       babl_format_with_space("R'G'B'A float", space),
+                       "linear", universal_linear_rgb_nonlinear_converter,
+                       NULL));
+       prep_conversion(babl_conversion_new(
+                       babl_format_with_space("RGBA float", space),
+                       babl_format_with_space("R'G'B'A float", babl),
+                       "linear", universal_linear_rgb_nonlinear_converter,
+                       NULL));
     }
 
     prep_conversion(babl_conversion_new(
index bbf0c428fbc0e9f342dad9d7e5fe1f96f15ebfb0..4c97cdbfa5df5c4919f75e0b30cc94ff160f257a 100644 (file)
@@ -41,6 +41,52 @@ typedef struct
 #endif
 } BablCMYK;
 
+typedef struct _BablSpectrumType BablSpectrumType;
+
+struct _BablSpectrumType {
+  double        nm_start;
+  double        nm_gap;
+  double        nm_end; /* last band, computed */
+  int           bands;
+};
+
+typedef struct
+{
+  BablSpectrumType spectrum_type;
+  int              is_spectral;
+  float           *observer_x;
+  float           *observer_y;
+  float           *observer_z;
+  float           *illuminant;
+  float            rev_y_scale;
+} BablSpectralSpace;
+
+typedef struct
+{
+  BablSpectralSpace *spectral_space;
+  int                inks;
+  float             *on_white;
+  float             *on_black;
+  float             *opaqueness;
+  float              scale;
+  float              trc_gamma;
+  float             *illuminant;
+} BablCoat;
+
+#define BABL_MAX_COATS 16
+
+typedef struct
+{
+  BablSpectralSpace *spectral_space;
+  BablCoat           coat_def[BABL_MAX_COATS];
+  int                coats;
+  float             *substrate;
+
+  int    stochastic_iterations;
+  float  stochastic_diffusion0;
+  float  stochastic_diffusion1;
+} BablProcessSpace;
+
 typedef struct
 {
   BablInstance     instance;
@@ -76,7 +122,6 @@ typedef struct
    */
   char *icc_profile;
   int   icc_length;
-
   BablCMYK cmyk;
 } BablSpace;
 
index 07d83058253aaeafab452ebcde0f92b845f5fa48..6c336767a082a4ce3d9e6595f468985757e2e677 100644 (file)
@@ -20,11 +20,15 @@ EXTRA_DIST=                         \
        tools/xml_insert.sh     \
        tools/changelog2rss     \
        index-static.html.in    \
+       ColorManagement.html    \
+       CMYK.html       \
+       SymmetricAlpha.html     \
        COPYING                 \
-       COPYING.LESSER \
+       toc                     \
+       COPYING.LESSER          \
        meson.build
 
-BUILT_EXTRA_DIST = index.html 
+BUILT_EXTRA_DIST = index.html ColorManagement.html CMYK.html SymmetricAlpha.html
 
 CLEANFILES = README changelog.rss
 DISTCLEANFILES = index-static.html $(BUILT_EXTRA_DIST)
@@ -36,6 +40,7 @@ index.html: index-static.html                    \
            $(top_srcdir)/AUTHORS                \
            $(top_srcdir)/TODO                   \
            $(top_srcdir)/NEWS                   \
+           toc                                  \
            Makefile.am
        echo -n "HTML: $@"
        cp $< $@ 
@@ -44,10 +49,11 @@ index.html: index-static.html                    \
        $(SHELL) $(top_srcdir)/docs/tools/xml_insert.sh $@ BablBase $$TMPFILE;\
        rm -f $$TMPFILE )
        echo -n "."
-
+       $(SHELL) $(top_srcdir)/docs/build-docs.sh $(top_srcdir) $(top_builddir)/docs
        $(SHELL) $(top_srcdir)/docs/tools/xml_insert.sh $@ AUTHORS $(top_srcdir)/AUTHORS
        $(SHELL) $(top_srcdir)/docs/tools/xml_insert.sh $@ TODO $(top_srcdir)/TODO
        $(SHELL) $(top_srcdir)/docs/tools/xml_insert.sh $@ NEWS $(top_srcdir)/NEWS
+       $(SHELL) $(top_srcdir)/docs/tools/xml_insert.sh $@ TOC $(top_srcdir)/docs/toc
        echo " [OK]"
 
 distclean-local:
index 9f4d228b687e1e437d05452a6bf6434358a60475..5ffe554aa8c44171ceb7fa10ee8c0298dade0716 100644 (file)
         <h1>Babl-@BABL_VERSION@</h1>
       </div>
     </div>
+<!--TOC-->
 
-    <div class='toc'>
-      <div class='print'>
-         <h3>Contents</h3>
-      </div>
-      <ul>
-        <li><a href='#Download'>&nbsp;&nbsp;Download</a></li>
-        <li><a href='#Features'>&nbsp;&nbsp;Features</a></li>
-        <li><a href='#ColorManagement'>&nbsp;&nbsp;Color Management</a></li>
-        <li><a href='#Symmetric-Alpha'>&nbsp;&nbsp;Symmetric-Alpha</a></li>
-        <li><a href='#CMYK'>&nbsp;&nbsp;CMYK</a></li>
-        <!--<li><a href='#Background'>Background</a></li>-->
-        <li><a href='#Usage'>&nbsp;&nbsp;Usage</a></li>
-        <li><a href='#Vocabulary'>&nbsp;&nbsp;Vocabulary</a></li>
-        <!--<li><a href='#Data-types'>&nbsp;&nbsp;&nbsp;&nbsp;Data types</a></li>
-        <li><a href='#Color-models'>&nbsp;&nbsp;&nbsp;&nbsp;Color models</a></li>
-        <li><a href='#Pixel-formats'>&nbsp;&nbsp;&nbsp;&nbsp;Pixel formats</a></li>-->
-
-        <li><a href='#Environment'>&nbsp;&nbsp;Environment</a></li>
-        <li><a href='#Extending'>&nbsp;&nbsp;Extending</a></li>
-        <li><a href='#DirectoryOverview'>&nbsp;&nbsp;Directory Overview</a></li>
-        <!--<li><a href='#ColorManagement'>Color Management</a></li>-->
-        <li><a href='#TODO'>&nbsp;&nbsp;Todo</a></li>
-
-        <li><a href='#Copyright'>&nbsp;&nbsp;Copyright</a></li>
-        <li><a href='#Authors'>&nbsp;&nbsp;Authors</a></li>
-      </ul>
-    </div>
 
 <div><a name='Babl'></a></div>
     <div class='paper'>
     <h2>Features</h2>
 
     <ul>
-      <li>ANSI C without external dependencies, works on win32, linux and mac,
-          32bit and 64bit systems.</li>
-      <li>Stable, small API, with singleton objects returned.</li>
-      <li>Extendable with new formats, color models, components and datatypes.</li>
-        <li>Can load <a href='#ColorManagement'>&nbsp;&nbsp;Color
-Spaces</a></li> from ICC v2 and v4 profiles containing RGB matrix + TRC, or <a
-href='#CMYK'>CMYK</a> profiles.</li>
-      <li><a href='#Symmetric-Alpha'>Symmetric-Alpha</a> no loss of color fidelity due to asymptotic behavior near alpha 0.0 in floating point.</li>
+      <li>Runtim-extendable with new formats, color models, components and datatypes, and SIMD code paths.</li>
       <li>Reference 64bit floating point conversions for datatypes and color
           models, with 32bit floating point reference speed-ups in some places.
       </li>
       <li>Runtime profiling/validating and code-path optimizing with persistence of profiling data across runs, with caching of results.</li>
+        <li>Can load <a href='ColorManagement.html'>Color Spaces</a> from ICC v2 and v4 profiles containing RGB matrix + TRC and with lcms2 dependency also <a
+href='CMYK.html'>CMYK</a> profiles.</li>
+      <li>Uses <a href='SymmetricAlpha.html'>Symmetric Alpha</a> conversions for conversions between separate and associate alpha, avoiding loss of color fidelity due to asymptotic behavior near alpha 0.0 in floating point.</li>
+      <li>Portable self contained C code working on win32, linux, bsds and mac
+on 32bit and 64bit systems.</li>
+      <li>Stable, small API, with singleton objects returned.</li>
     </ul>
 
-    <p><a href='http://www.gegl.org/'>GEGL</a> through <a
-    href='http://www.gegl.org/api.html#GeglBuffer'>GeglBuffer</a> provides
-    tiled buffers with on disk storage as well as linear buffers with accessor
-    functions for efficient data access transparently using babl fishes for
-    translation to the desired pixel formats.</p>
+    <p>The pixel data storage in <a href='https://www.gimp.org/'>GIMP</a> uses
+<a href='http://www.gegl.org/'>GEGL</a>'s GeglBuffer which internally stores
+tiles and provides an API for retrieving and storing pixel data with implicit
+conversions using babl formats.
+    </p>
 
     <a name='Download'></a>
     <h2>Download</h2>
@@ -156,114 +129,16 @@ href='#CMYK'>CMYK</a> profiles.</li>
     to the GEGL release.</p>
 
     <!--NEWS-->
-    For more news see git log.
-
-
-  <a name='ColorManagement'></a>
-  <h2>Color Management</h2>
-
-  <p>All pixel formats in babl have a specified color space, if NULL is passed
-as a space constants for (unbounded) linear sRGB data is assumed, data being
-sRGB defines the conversion to and from gray-scale as well as the gamma
-  - or Transfer Response Curve, TRC, used for converting between linear and
-    non-linear variants of the data.</p>
-
-  <p>babl has API for creating a format for a specific space:
-<tt>babl_format_with_space("R'G'B' u16", babl_space ("Rec2020"))</tt> creates a
-16 bit integer format for the Rec2020 color space. Babl knows internally about
-"sRGB", "Rec2020", "Adobe", "Apple", "ProPhoto", "ACEScg" and "ACES2065-1"
-spaces, as they are defined with constants on their wikipedia pages or similar upstream references.</p>
-
-  <p>Additional spaces can be loaded from monitor-class matrix+TRC ICC v2 and
-  v4 profiles. Using babl_icc_make_space (see babl.h for details). The space of
-  a babl format can also be queried with babl_format_get_space.
-  </p>
-
-  <a name='Symmetric-Alpha'></a>
-  <h2>Symmetric transformations for floating point alpha</h2>
-
+    For more detailed changes see git log.
 
-  <p> babl clamps the alpha used when going from separate alpha to associated
-alpha or from associated alpha to separate alpha to BABL_ALPHA_FLOOR. This
-replaces asymptotic behavior and direct precision loss of color precision when
-multiplying or dividing by alphas near 0.0 with a consistent symmetric
-transformation.</p>
-
-<p>Original intent of data as well as non-asymptotic precision loss is thus
-maintained when the processing chain might temporarily use the other alpha
-representation.</p>
-
-<pre>
-    #define BABL_ALPHA_FLOOR    (1.0/65536.0)
-    #define BABL_ALPHA_FLOOR_F  (1.0f/65536.0f)
-</pre>
-
-<p>The deviation from not clamping near 0.0 is within the quantization margin
-of 16bit integer alpha, thus no adaptations for any SIMD or and similar 8bit
-and 16bit extensions of pixel format conversions are needed.
-  </p>
-
-   <p>This is the clamping function in use:</p>
-<pre>
-static inline float
-babl_epsilon_for_zero_float (float value)
-{
- if (value &lt;= BABL_ALPHA_FLOOR_F)
- {
-   /* for performance one could directly retun BABL_ALPHA_FLOOR_F here
-      and dropping handling negative values consistently. */
-   if (value &gt;= 0.0f)
-     return BABL_ALPHA_FLOOR_F;
-   else if (value &gt;= -BABL_ALPHA_FLOOR_F)
-     return -BABL_ALPHA_FLOOR_F;
- }
- return value;  /* most common case, return input value */
-}
-</pre>
-<p>And an example use of this clamping function that is consistent with babls behavior:</p>
-<pre>
-static inline void
-associated_to_separate_rgba (const float *associated_rgba,
-                                   float *separate_rgba)
-{
-  float alpha = associated_rgba[3];
-  float clamped_alpha = babl_epsilon_for_zero_float (alpha);
-  float reciprocal_alpha = 1.0f / clamped_alpha;
-
-  separate_rgba[0] = associated_rgba[0] * reciprocal_alpha;
-  separate_rgba[1] = associated_rgba[1] * reciprocal_alpha;
-  separate_rgba[2] = associated_rgba[2] * reciprocal_alpha;
-  separate_rgba[3] = alpha;
-}
-</pre>
-
-
-<p>For more detils see <a href='https://gitlab.gnome.org/GNOME/babl/commit/a4d607843d3cab18745d547fc8a46dec51dcea5e'>the commit message of the most recent refinement</a> as well as <a href='https://www.patreon.com/posts/premultiplied-in-21014115'>blog post with further background</a>.</p>
-
-
-  <a name='CMYK'></a>
-  <h2>CMYK</h2>
-
-  <p>CMYK handling is done using babl-spaces created with ICC profiles
-containing CMYK profiles. BablSpaces for these ICC profiles handle color conversions using lcms2 - or if compiled without lcms2 support a naive profile independent fallback.</p>
-  <p>When a babl space derived from a CMYK ICC profile is used to instantiate
-RGB formats, the resulting formats are using the default/NULL space for
-primaries and TRCs.</p>
-
-  <p>The CMYK formats that use lcms2 for color interchange with the rest of
-babl are the following, which are available for all data types, u8, u16, half
-and float:</p>
-  <dl>
-     <dt>CMYK</dt><dd>Cyan Magenta Yellow Key, with 0 being white and 1.0 full ink coverage.</dd>
-     <dt>CMYKA</dt><dd>as previous, with separate alpha channel</dd>
-     <dt>CaMaYaKaA</dt><dd>as previous but associated alpha</dd>
-     <dt>cmyk</dt><dd>inverted CMYK, where 0.0 is full ink coverage and 1.0 is none</dd>
-     <dt>cmykA</dt><dd>as previous, with separate alpha channel</dd>
-     <dt>camayakaA</dt><dd>as previous but associated alpha</dd>
-  </dl>
 
     <a name='Usage'></a>
     <h2>Usage</h2>
+    <p>Most users of babl do not know they are using babl and it is GIMP itself
+    which uses babl, this is documentation for such uses - and others that might
+    want to use babl for pixel format or color space conversion in other software.
+</p>
+
     <p>When using BablFishes to do your conversions, you request a fish to
     convert between two formats, and an optimal fish to babls capability is
     provided that you can use to do your conversions. Babl also provides
index b63e767cad41a4fb3d0d7a610dc548e10b853531..0f4671304a5ef88997d26477205dec0bb5708fd7 100644 (file)
@@ -41,6 +41,7 @@ index_html = custom_target('index.html',
     join_paths(meson.source_root(), 'AUTHORS'),
     join_paths(meson.source_root(), 'TODO'),
     join_paths(meson.source_root(), 'NEWS'),
+    'toc',
   ],
   output: [ 'index.html', ],
   command: [
@@ -50,6 +51,50 @@ index_html = custom_target('index.html',
     '&&', xml_insert, '@OUTPUT@', 'AUTHORS',  '@INPUT2@',
     '&&', xml_insert, '@OUTPUT@', 'TODO',     '@INPUT3@',
     '&&', xml_insert, '@OUTPUT@', 'NEWS',     '@INPUT4@',
+    '&&', xml_insert, '@OUTPUT@', 'toc',     '@INPUT5@',
+  ],
+  build_by_default: true,
+)
+
+
+CMYK_html = custom_target('CMYK.html',
+  input : [
+    'CMYK-static.html',
+    'toc',
+  ],
+  output: [ 'CMYK.html', ],
+  command: [
+    env_bin,
+    'cp', '@INPUT0@', '@OUTPUT@',
+    '&&', xml_insert, '@OUTPUT@', 'toc',     '@INPUT1@',
+  ],
+  build_by_default: true,
+)
+
+ColorManagement_html = custom_target('ColorManagement.html',
+  input : [
+    'ColorManagement-static.html',
+    'toc',
+  ],
+  output: [ 'ColorManagement.html', ],
+  command: [
+    env_bin,
+    'cp', '@INPUT0@', '@OUTPUT@',
+    '&&', xml_insert, '@OUTPUT@', 'toc',     '@INPUT1@',
+  ],
+  build_by_default: true,
+)
+
+SymmetricAlpha_html = custom_target('SymmetricAlpha.html',
+  input : [
+    'SymmetricAlpha-static.html',
+    'toc',
+  ],
+  output: [ 'SymmetricAlpha.html', ],
+  command: [
+    env_bin,
+    'cp', '@INPUT0@', '@OUTPUT@',
+    '&&', xml_insert, '@OUTPUT@', 'toc',     '@INPUT1@',
   ],
   build_by_default: true,
 )
index 8ac6b353878034a33ec039b147efb94a31d8b94c..de3bbd1621ae215278f447e9c597e76ecc67a31c 100644 (file)
@@ -3,12 +3,67 @@
 #include "../config.h"
 #include "babl/babl-internal.h"
 
+//#define SPACE1 babl_space("ProPhoto")
+#define SPACE1 babl_space("Apple")
+//#define SPACE1 babl_space("sRGB")
+//#define SPACE2 babl_space("Apple")
+
+static int
+file_get_contents (const char  *path,
+                         char       **contents,
+                         long        *length,
+                         void        *error)
+{
+  FILE *file;
+  long  size;
+  char *buffer;
+
+  file = fopen (path,"rb");
+
+  if (!file)
+    return -1;
+
+  if (fseek (file, 0, SEEK_END) == -1 || (size = ftell (file)) == -1)
+    {
+      fclose (file);
+      return -1;
+    }
+  if (length) *length = size;
+  rewind (file);
+  if ((size_t) size > SIZE_MAX - 8)
+    {
+      fclose (file);
+      return -1;
+    }
+  buffer = calloc(size + 8, 1);
+
+  if (!buffer)
+    {
+      fclose(file);
+      return -1;
+    }
+
+  size -= fread (buffer, 1, size, file);
+  if (size)
+    {
+      fclose (file);
+      free (buffer);
+      return -1;
+    }
+  fclose (file);
+  *contents = buffer;
+  return 0;
+}
+
 int 
 main (int    argc, 
       char **argv)
 {
   int final = 0;
   const Babl *fish;
+  const Babl *SPACE2 = NULL;
+
+
   if (argc < 3)
   {
     fprintf (stderr, "need two args, from and to babl-formats\n");
@@ -25,22 +80,42 @@ main (int    argc,
 
   babl_init ();
 
-  fish = babl_fish (babl_format(argv[1]), babl_format (argv[2]));
+#define ICC_PATH "/tmp/my.icc"
+//#define ICC_PATH "/usr/share/color/icc/colord/AppleRGB.icc"
+//#define ICC_PATH "/tmp/ACEScg-elle-V2-labl.icc"
+//#define ICC_PATH "/tmp/ACEScg-elle-V2-g10.icc"
+//#define ICC_PATH "/tmp/ACEScg-elle-V4-g10.icc"
+//#define ICC_PATH "/tmp/ACEScg-elle-V4-g22.icc"
+
+
+  {
+    char *icc_data = NULL;
+    long     length = 0;
+    file_get_contents (ICC_PATH, &icc_data, &length, NULL);
+    SPACE2 = babl_space_from_icc (icc_data, length, BABL_ICC_INTENT_RELATIVE_COLORIMETRIC, NULL);
+    //SPACE2 = babl_space ("sRGB");
+  }
+
+  fish = babl_fish (babl_format_with_space(argv[1], SPACE1), babl_format_with_space (argv[2], SPACE2));
   if (!fish)
+  {
+    fprintf (stderr, "!!!! %s %s\n", argv[1], argv[2]);
     return -1;
+  }
 
   if (final)
   switch (fish->class_type)
   {
     case BABL_FISH:
-      fprintf (stderr, "%s\n", babl_get_name (fish));
+      fprintf (stderr, ">%s\n", babl_get_name (fish));
       break;
     case BABL_FISH_PATH:
-      fprintf (stderr, "chosen %s to %s: steps: %i error: %f cost: %f\n", argv[1], argv[2], fish->fish_path.conversion_list->count, fish->fish.error, fish->fish_path.cost);
+      fprintf (stderr, "chosen %s to %s: steps: %i error: %.12f cost: %f\n", argv[1], argv[2], fish->fish_path.conversion_list->count, fish->fish.error, fish->fish_path.cost);
         for (int i = 0; i < fish->fish_path.conversion_list->count; i++)
           {
-            fprintf (stderr, "\t%s\n",
-                      babl_get_name(fish->fish_path.conversion_list->items[i]  ));
+            fprintf (stderr, "\t%s (cost: %li)\n",
+                      babl_get_name(fish->fish_path.conversion_list->items[i]  ), 
+    fish->fish_path.conversion_list->items[i]->conversion.cost);
           }
       break;
   }