babl-fish-reference: implement floating point version of reference path
authorØyvind Kolås <pippin@gimp.org>
Wed, 29 Aug 2018 13:28:41 +0000 (15:28 +0200)
committerØyvind Kolås <pippin@gimp.org>
Wed, 29 Aug 2018 13:28:41 +0000 (15:28 +0200)
This relies on conversions, linear or planar, being registered to and from
RGBA float, similar to the already existing reference conversions in double.

To enable use of it set the environment variable BABL_REFERENCE_FLOAT to any
value, babl will crash if the above requirement is not met for a requested
conversion - permitting adding it - fallback code could be added that implements
it using the double versions when missing - but not having a full coverage at
least for the commonly used formats defeats the purpose.

babl/babl-fish-reference.c

index 3eff1cad358195e747d08c2bb9fa5c0fd3344483..7ae5455d5bb9449a49f2320711bf323bcc4fad15 100644 (file)
@@ -97,6 +97,9 @@ create_name (const Babl *source,
 
 #endif
 
+/* need an internal version that only ever does double,
+ * for use in path evaluation? and perhaps even self evaluation of float code path?
+ */
 Babl *
 babl_fish_reference (const Babl *source,
                      const Babl *destination)
@@ -606,7 +609,6 @@ process_same_model (const Babl  *babl,
                     char       *destination,
                     long        n)
 {
-  void *double_buf;
   const void *type_float = babl_type_from_id (BABL_FLOAT);
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
   if (BABL (babl->fish.source) == BABL (babl->fish.destination))
@@ -619,67 +621,68 @@ process_same_model (const Babl  *babl,
   }
 
 
-  double_buf = babl_malloc (sizeof (double) * n *
+
+
+  if ((babl->fish.source->format.type[0]->bits < 32 ||
+       babl->fish.source->format.type[0] == type_float) &&
+      (babl->fish.destination->format.type[0]->bits < 32 ||
+       babl->fish.destination->format.type[0] == type_float))
+  {
+     void *float_buf = babl_malloc (sizeof (float) * n *
                             MAX (BABL (babl->fish.source)->format.model->components,
                                  BABL (babl->fish.source)->format.components));
-#undef MAX
-
-  if (compatible_components ((void*)babl->fish.source,
-                             (void*)babl->fish.destination))
+    if (compatible_components ((void*)babl->fish.source,
+                               (void*)babl->fish.destination))
     {
-
-      if ((babl->fish.source->format.type[0]->bits < 32 ||
-           babl->fish.source->format.type[0] == type_float) &&
-          (babl->fish.destination->format.type[0]->bits < 32 ||
-           babl->fish.destination->format.type[0] == type_float))
-      {
         ncomponent_convert_to_float (
           (BablFormat *) BABL (babl->fish.source),
           (char *) source,
-          double_buf,
+          float_buf,
           n);
         ncomponent_convert_from_float (
           (BablFormat *) BABL (babl->fish.destination),
-          double_buf,
+          float_buf,
           (char *) destination,
           n);
-      }
-      else
-      {
-        ncomponent_convert_to_double (
+    }
+    else
+    {
+        convert_to_float (
           (BablFormat *) BABL (babl->fish.source),
           (char *) source,
-          double_buf,
+          float_buf,
           n);
-        ncomponent_convert_from_double (
+
+        convert_from_float (
           (BablFormat *) BABL (babl->fish.destination),
-          double_buf,
+          float_buf,
           (char *) destination,
           n);
-      }
     }
+    babl_free (float_buf);
+  }
   else
+  {
+     void *double_buf = babl_malloc (sizeof (double) * n *
+                            MAX (BABL (babl->fish.source)->format.model->components,
+                                 BABL (babl->fish.source)->format.components));
+#undef MAX
+    if (compatible_components ((void*)babl->fish.source,
+                               (void*)babl->fish.destination))
     {
-
-      if ((babl->fish.source->format.type[0]->bits < 32 ||
-           babl->fish.source->format.type[0] == type_float) &&
-          (babl->fish.destination->format.type[0]->bits < 32 ||
-           babl->fish.destination->format.type[0] == type_float))
-      {
-        convert_to_float (
+        ncomponent_convert_to_double (
           (BablFormat *) BABL (babl->fish.source),
           (char *) source,
           double_buf,
           n);
-
-        convert_from_float (
+        ncomponent_convert_from_double (
           (BablFormat *) BABL (babl->fish.destination),
           double_buf,
           (char *) destination,
           n);
-      }
-      else
-      {
+    }
+    else
+    {
         convert_to_double (
           (BablFormat *) BABL (babl->fish.source),
           (char *) source,
@@ -691,9 +694,9 @@ process_same_model (const Babl  *babl,
           double_buf,
           (char *) destination,
           n);
-      }
     }
-  babl_free (double_buf);
+    babl_free (double_buf);
+  }
 }
 
 void
@@ -709,6 +712,10 @@ babl_fish_reference_process (const Babl *babl,
   Babl *rgba_image = NULL;
   Babl *destination_image = NULL;
 
+  static int allow_float_reference = -1;
+  if (allow_float_reference == -1)
+    allow_float_reference = getenv ("BABL_REFERENCE_FLOAT") ? 1 : 0;
+
   if ((BABL (babl->fish.source)->format.model ==
        BABL (babl->fish.destination)->format.model) &&
       (BABL (babl->fish.source)->format.space ==
@@ -725,57 +732,75 @@ babl_fish_reference_process (const Babl *babl,
     return;
   }
 
-  if (0 && (babl->fish.source->format.type[0]->bits < 32 ||
+  if (allow_float_reference &&
+      (babl->fish.source->format.type[0]->bits < 32 ||
       babl->fish.source->format.type[0] == type_float) &&
       (babl->fish.destination->format.type[0]->bits < 32 ||
       babl->fish.destination->format.type[0] == type_float))
   {
-/* this code path is wip - not quite working yet, and needs resyncing
-   with double code that has gotten unneeded buffer allocation/copying
-   improvements  */
-  void *source_float_buf;
-  void *rgba_float_buf;
-  void *destination_float_buf;
-
-  source_float_buf = babl_malloc (sizeof (float) * n *
-                                   BABL (babl->fish.source)->format.model->components);
-  rgba_float_buf        = babl_malloc (sizeof (float) * n * 4);
-  destination_float_buf = babl_malloc (sizeof (float) * n *
-                                        BABL (babl->fish.destination)->format.model->components);
-
-  source_image = babl_image_from_linear (
-    source_float_buf, BABL (BABL ((babl->fish.source))->format.model));
-  rgba_image = babl_image_from_linear (
-    rgba_float_buf, babl_format_with_space ("RGBA float",
-           BABL (BABL ((babl->fish.source))->format.space)));
-  destination_image = babl_image_from_linear (
-    destination_float_buf, babl_format_with_space ("RGBA float",
-                          BABL (BABL ((babl->fish.destination))->format.space)));
-
-  convert_to_float (
-    (BablFormat *) BABL (babl->fish.source),
-    source,
-    source_float_buf,
-    n
-  );
+    void *source_float_buf_alloc = NULL;
+    void *source_float_buf;
+    void *rgba_float_buf_alloc = NULL;
+    void *rgba_float_buf;
+    void *destination_float_buf_alloc = NULL;
+    void *destination_float_buf;
+
+    if (babl->fish.source->format.type[0] == type_float &&
+        BABL(babl->fish.source)->format.components ==
+        BABL(babl->fish.source)->format.model->components && 0)
+    {
+      source_float_buf = (void*)source;
+      source_image = babl_image_from_linear (
+         source_float_buf,
+         babl_format_with_model_as_type ((void*)((babl->fish.source))->format.model,
+         type_float));
+    }
+    else
+    {
+      source_float_buf_alloc = babl_malloc (sizeof (float) * n *
+                                  BABL (babl->fish.source)->format.model->components);
 
-  {
-    char src_name[256];
-    Babl *conv;
-    if (babl->fish.source->class_type == BABL_FORMAT)
-    sprintf (src_name, "%s float",
-         babl_get_name (BABL (babl->fish.source->format.model)));
-    else if (babl->fish.source->class_type == BABL_MODEL)
-    sprintf (src_name, "%s float",
-         babl_get_name (BABL (babl->fish.source)));
-
-    conv =
-      assert_conversion_find (
-         babl_format_with_space (src_name,
-                BABL (babl->fish.source)),
-         babl_format_with_space ("RGBA float",
-           BABL (BABL ((babl->fish.source))->format.space))
+      source_float_buf = source_float_buf_alloc;
+      source_image = babl_image_from_linear (
+        source_float_buf,
+      babl_format_with_model_as_type (BABL(BABL ((babl->fish.source))->format.model),
+         type_float));
+      convert_to_float (
+        (BablFormat *) BABL (babl->fish.source),
+        source,
+        source_float_buf,
+        n
       );
+    }
+
+    if (babl_model_is ((void*)babl->fish.source->format.model, "RGBA"))
+    {
+      rgba_float_buf = source_float_buf;
+      rgba_image = babl_image_from_linear (
+          rgba_float_buf,
+          (void*)babl->fish.source->format.model);
+    }
+    else
+    {
+      char src_name[256];
+      Babl *conv;
+
+      sprintf (src_name, "%s float", babl_get_name((void*)babl->fish.source->format.model));
+      conv =
+        assert_conversion_find (
+        babl_format_with_space (src_name,
+                   BABL (BABL ((babl->fish.source))->format.space)),
+        babl_format_with_space ("RGBA float",
+                   BABL (BABL ((babl->fish.source))->format.space)));
+
+      rgba_float_buf_alloc  = babl_malloc (sizeof (float) * n * 4);
+      rgba_float_buf        = rgba_float_buf_alloc;
+
+      rgba_image = babl_image_from_linear (
+          rgba_float_buf,
+        babl_format_with_space ("RGBA float",
+                   BABL (BABL ((babl->fish.source))->format.space)));
+
 
     if (conv->class_type == BABL_CONVERSION_PLANAR)
       {
@@ -791,40 +816,56 @@ babl_fish_reference_process (const Babl *babl,
           source_float_buf, rgba_float_buf,
           n);
       }
-    else babl_fatal ("oops");
-  }
 
-  if (((babl->fish.source)->format.space !=
-      ((babl->fish.destination)->format.space)))
-  {
-    float matrix[9];
-    float *rgba = rgba_float_buf;
-    babl_matrix_mul_matrixf (
-      (babl->fish.destination)->format.space->space.XYZtoRGBf,
-      (babl->fish.source)->format.space->space.RGBtoXYZf,
-      matrix);
-
-    babl_matrix_mul_vectorff_buf4 (matrix, rgba, rgba, n);
-  }
 
-  {
-    char dst_name[256];
-    Babl *conv;
-    if (babl->fish.destination->class_type == BABL_FORMAT)
-    sprintf (dst_name, "%s float",
-         babl_get_name (BABL (babl->fish.destination->format.model)));
-    else if (babl->fish.destination->class_type == BABL_MODEL)
-    sprintf (dst_name, "%s float",
-         babl_get_name (BABL (babl->fish.destination)));
-    conv =
-      assert_conversion_find (
-         babl_format_with_space ("RGBA float",
-           BABL (BABL ((babl->fish.destination))->format.space)),
-         babl_format_with_space (dst_name,
-                BABL (babl->fish.destination)));
+    }
 
-    if (conv->class_type == BABL_CONVERSION_PLANAR)
+    if (((babl->fish.source)->format.space !=
+        ((babl->fish.destination)->format.space)))
+    {
+      float matrix[9];
+      float *rgba = rgba_float_buf;
+      babl_matrix_mul_matrixf (
+        (babl->fish.destination)->format.space->space.XYZtoRGBf,
+        (babl->fish.source)->format.space->space.RGBtoXYZf,
+        matrix);
+
+      babl_matrix_mul_vectorff_buf4 (matrix, rgba, rgba, n);
+    }
+
+    {
+      char dst_name[256];
+      Babl *conv;
+      const Babl *destination_float_format;
+      sprintf (dst_name, "%s float", babl_get_name((void*)babl->fish.destination->format.model));
+      destination_float_format =
+        babl_format_with_space (dst_name,
+                   BABL (BABL ((babl->fish.destination))->format.space));
+
+      if(
+        babl_format_with_space ("RGBA float",
+                   BABL (BABL ((babl->fish.destination))->format.space)) ==
+        babl_format_with_space (dst_name,
+                   BABL (BABL ((babl->fish.destination))->format.space)))
+      {
+         destination_float_buf = rgba_float_buf;
+      }
+      else
       {
+         destination_float_buf_alloc = babl_malloc (sizeof (float) * n *
+                                         BABL (babl->fish.destination)->format.model->components);
+         destination_float_buf = destination_float_buf_alloc;
+      conv =
+        assert_conversion_find (
+        babl_format_with_space ("RGBA float",
+                   BABL (BABL ((babl->fish.destination))->format.space)),
+        babl_format_with_space (dst_name,
+                   BABL (BABL ((babl->fish.destination))->format.space)));
+
+      if (conv->class_type == BABL_CONVERSION_PLANAR)
+        {
+          destination_image = babl_image_from_linear (
+            destination_float_buf, destination_float_format);
         babl_conversion_process (
           conv,
           (void*)rgba_image, (void*)destination_image,
@@ -837,19 +878,23 @@ babl_fish_reference_process (const Babl *babl,
           rgba_float_buf, destination_float_buf,
           n);
       }
-    else babl_fatal ("oops");
-  }
 
-  convert_from_float (
-    (BablFormat *) BABL (babl->fish.destination),
-    destination_float_buf,
-    destination,
-    n
-  );
+      }
+   }
 
-  babl_free (destination_float_buf);
-  babl_free (rgba_float_buf);
-  babl_free (source_float_buf);
+    convert_from_float (
+      (BablFormat *) BABL (babl->fish.destination),
+      destination_float_buf,
+      destination,
+      n
+    );
+
+    if (destination_float_buf_alloc)
+      babl_free (destination_float_buf_alloc);
+    if (rgba_float_buf_alloc)
+      babl_free (rgba_float_buf_alloc);
+    if (source_float_buf_alloc)
+      babl_free (source_float_buf_alloc);
   }
   else /*   double  */
   {
@@ -859,12 +904,11 @@ babl_fish_reference_process (const Babl *babl,
     void *rgba_double_buf;
     void *destination_double_buf_alloc = NULL;
     void *destination_double_buf;
-  
+
     if (babl->fish.source->format.type[0] == type_double &&
-        BABL(babl->fish.source)->format.components == 
+        BABL(babl->fish.source)->format.components ==
         BABL(babl->fish.source)->format.model->components && 0)
     {
-      fprintf (stderr, "hita\n");
       source_double_buf = (void*)source;
       source_image = babl_image_from_linear (
          source_double_buf, BABL (BABL ((babl->fish.source))->format.model));
@@ -873,7 +917,7 @@ babl_fish_reference_process (const Babl *babl,
     {
       source_double_buf_alloc = babl_malloc (sizeof (double) * n *
                                   BABL (babl->fish.source)->format.model->components);
-  
+
       source_double_buf = source_double_buf_alloc;
       source_image = babl_image_from_linear (
         source_double_buf, BABL (BABL ((babl->fish.source))->format.model));
@@ -949,7 +993,6 @@ babl_fish_reference_process (const Babl *babl,
       }
       else
       {
-    /* XXX : do this with format instead of model - more generic */
       Babl *conv =
         assert_conversion_find (destination_rgba_format,
            BABL (babl->fish.destination)->format.model);