babl-fish-reference: do some conversions in single precision float
authorØyvind Kolås <pippin@gimp.org>
Mon, 27 Aug 2018 20:57:54 +0000 (22:57 +0200)
committerØyvind Kolås <pippin@gimp.org>
Mon, 27 Aug 2018 22:37:12 +0000 (00:37 +0200)
This permits these conversions to go through floating point instead of double
precision when non of the involved format have more than 32bit precision,
this might be determinetal to u32 but is right for u8 and u16 which we rely
most on.

We also disable the missing fast path messages, since now many references;
through internal shortcuts are faster than some long chains, perhaps some
of these reference fast paths should be split out as new categories of fishes.

babl/babl-fish-path.c
babl/babl-fish-reference.c
babl/base/type-float.c
babl/base/type-u16.c
babl/base/type-u8.c

index 2e87268109763825cc1ccb6164478b91ffd6a00a..14b759f5c2152c87b9c0ee0550c5a3e85a5899eb 100644 (file)
@@ -627,7 +627,7 @@ babl_fish_path2 (const Babl *source,
       babl_free (babl);
       babl_mutex_unlock (babl_format_mutex);
 
-      _babl_fish_missing_fast_path_warning (source, destination);
+      //_babl_fish_missing_fast_path_warning (source, destination);
 
       return NULL;
     }
index 27040ae01c796ad3cd9b4c738f94f7740cc29dfb..12b93d0cddbf5ee995941ee789c5fbe9cd730f45 100644 (file)
@@ -279,6 +279,135 @@ convert_from_double (BablFormat *destination_fmt,
   babl_free (dst_img);
 }
 
+static void
+convert_to_float (BablFormat *source_fmt,
+                  const char *source_buf,
+                  char       *float_buf,
+                  int         n)
+{
+  int        i;
+
+  BablImage *src_img;
+  BablImage *dst_img;
+
+  src_img = (BablImage *) babl_image_new (
+    babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+  dst_img = (BablImage *) babl_image_new (
+    babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+
+  dst_img->type[0]  = (BablType *) babl_type_from_id (BABL_FLOAT);
+  dst_img->pitch[0] =
+    (dst_img->type[0]->bits / 8) * source_fmt->model->components;
+  dst_img->stride[0] = 0;
+
+  src_img->type[0]   = (BablType *) babl_type_from_id (BABL_FLOAT);
+  src_img->pitch[0]  = source_fmt->bytes_per_pixel;
+  src_img->stride[0] = 0;
+
+  {
+  /* i is dest position */
+  for (i = 0; i < source_fmt->model->components; i++)
+    {
+      int j;
+      int found = 0;
+
+      dst_img->data[0] =
+        float_buf + (dst_img->type[0]->bits / 8) * i;
+
+      src_img->data[0] = (char *)source_buf;
+
+      /* j is source position */
+      for (j = 0; j < source_fmt->components; j++)
+        {
+          src_img->type[0] = source_fmt->type[j];
+
+          if (source_fmt->component[j] ==
+              source_fmt->model->component[i])
+            {
+              babl_conversion_process (assert_conversion_find (src_img->type[0], dst_img->type[0]),
+                                       (void*)src_img, (void*)dst_img, n);
+              found = 1;
+              break;
+            }
+
+          src_img->data[0] += src_img->type[0]->bits / 8;
+        }
+
+      if (!found)
+        {
+          char *dst_ptr = dst_img->data[0];
+          float value;
+
+          value = source_fmt->model->component[i]->instance.id == BABL_ALPHA ? 1.0 : 0.0;
+
+          for (j = 0; j < n; j++)
+            {
+              float *dst_component = (float *) dst_ptr;
+
+              *dst_component = value;
+              dst_ptr += dst_img->pitch[0];
+            }
+        }
+    }
+  }
+  babl_free (src_img);
+  babl_free (dst_img);
+}
+
+
+static void
+convert_from_float (BablFormat *destination_fmt,
+                     char      *destination_float_buf,
+                     char      *destination_buf,
+                     int        n)
+{
+  int        i;
+
+  BablImage *src_img;
+  BablImage *dst_img;
+
+  src_img = (BablImage *) babl_image_new (
+    babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+  dst_img = (BablImage *) babl_image_new (
+    babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+
+  src_img->type[0]   = (BablType *) babl_type_from_id (BABL_FLOAT);
+  src_img->pitch[0]  = (src_img->type[0]->bits / 8) * destination_fmt->model->components;
+  src_img->stride[0] = 0;
+
+  dst_img->data[0]  = destination_buf;
+  dst_img->type[0]  = (BablType *) babl_type_from_id (BABL_FLOAT);
+  dst_img->pitch[0] = destination_fmt->bytes_per_pixel;
+  dst_img->stride[0] = 0;
+
+  for (i = 0; i < destination_fmt->components; i++)
+    {
+      int j;
+
+      dst_img->type[0] = destination_fmt->type[i];
+
+      for (j = 0; j < destination_fmt->model->components; j++)
+        {
+          if (destination_fmt->component[i] ==
+              destination_fmt->model->component[j])
+            {
+              src_img->data[0] =
+                destination_float_buf + (src_img->type[0]->bits / 8) * j;
+
+              babl_conversion_process (assert_conversion_find (src_img->type[0],
+                                       dst_img->type[0]),
+                                       (void*)src_img, (void*)dst_img, n);
+              break;
+            }
+        }
+
+      dst_img->data[0] += dst_img->type[0]->bits / 8;
+    }
+  babl_free (src_img);
+  babl_free (dst_img);
+}
+
+
 
 static void
 ncomponent_convert_to_double (BablFormat       *source_fmt,
@@ -350,6 +479,77 @@ ncomponent_convert_from_double (BablFormat *destination_fmt,
 }
 
 
+static void
+ncomponent_convert_to_float (BablFormat       *source_fmt,
+                             char             *source_buf,
+                             char             *source_float_buf,
+                             int               n)
+{
+  BablImage *src_img;
+  BablImage *dst_img;
+
+  src_img = (BablImage *) babl_image_new (
+    babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+  dst_img = (BablImage *) babl_image_new (
+    babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+
+  dst_img->type[0]  = (BablType *) babl_type_from_id (BABL_FLOAT);
+  dst_img->pitch[0] = (dst_img->type[0]->bits / 8);
+  dst_img->stride[0] = 0;
+
+  src_img->data[0] = source_buf;
+  src_img->type[0] = source_fmt->type[0];
+  src_img->pitch[0] = source_fmt->type[0]->bits / 8;
+  src_img->stride[0] = 0;
+
+  dst_img->data[0] = source_float_buf;
+
+  babl_conversion_process (
+    assert_conversion_find (src_img->type[0], dst_img->type[0]),
+    (void*)src_img, (void*)dst_img,
+    n * source_fmt->components);
+  babl_free (src_img);
+  babl_free (dst_img);
+}
+
+static void
+ncomponent_convert_from_float (BablFormat *destination_fmt,
+                               char       *destination_float_buf,
+                               char       *destination_buf,
+                               int         n)
+{
+  BablImage *src_img;
+  BablImage *dst_img;
+
+  src_img = (BablImage *) babl_image_new (
+    babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+  dst_img = (BablImage *) babl_image_new (
+    babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+
+  src_img->type[0]   = (BablType *) babl_type_from_id (BABL_FLOAT);
+  src_img->pitch[0]  = (src_img->type[0]->bits / 8);
+  src_img->stride[0] = 0;
+
+  dst_img->data[0]  = destination_buf;
+  dst_img->type[0]  = (BablType *) babl_type_from_id (BABL_FLOAT);
+  dst_img->pitch[0] = destination_fmt->type[0]->bits/8;
+  dst_img->stride[0] = 0;
+
+  dst_img->type[0] = destination_fmt->type[0];
+  src_img->data[0] = destination_float_buf;
+
+  babl_conversion_process (
+    assert_conversion_find (src_img->type[0], dst_img->type[0]),
+    (void*)src_img, (void*)dst_img,
+    n * destination_fmt->components);
+
+  dst_img->data[0] += dst_img->type[0]->bits / 8;
+  babl_free (src_img);
+  babl_free (dst_img);
+}
+
+
+
 static int
 process_to_n_component (const Babl  *babl,
                         const char *source,
@@ -388,12 +588,33 @@ process_to_n_component (const Babl  *babl,
   return 0;
 }
 
+static int compatible_components (const BablFormat *a,
+                                  const BablFormat *b)
+{
+  int i;
+  if (a->components != b->components)
+    return 0;
+  for (i = 0; i < a->components; i++)
+   if (a->component[i] != b->component[i])
+     return 0;
+  return 1;
+}
+
 static void
 process_same_model (const Babl  *babl,
                     const char *source,
                     char       *destination,
                     long        n)
 {
+  if (BABL (babl->fish.source)== BABL (babl->fish.destination))
+  {
+    if (source == destination)
+    {
+      memcpy (destination, source, n * babl->fish.source->format.bytes_per_pixel);
+    }
+    return;
+  }
+
   void *double_buf;
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
 
@@ -402,27 +623,68 @@ process_same_model (const Babl  *babl,
                                  BABL (babl->fish.source)->format.components));
 #undef MAX
 
-  if ((BABL (babl->fish.source)->format.components ==
-       BABL (babl->fish.destination)->format.components)
-      && (BABL (babl->fish.source)->format.model->components !=
-          BABL (babl->fish.source)->format.components))
+  if (compatible_components ((void*)babl->fish.source,
+                             (void*)babl->fish.destination))
     {
-      ncomponent_convert_to_double (
+      if (BABL (babl->fish.source)->format.type[0]->bits < 32 ||
+          BABL (babl->fish.destination)->format.type[0]->bits < 32)
+      {
+        ncomponent_convert_to_float (
+          (BablFormat *) BABL (babl->fish.source),
+          (char *) source,
+          double_buf,
+          n
+        );
+
+          ncomponent_convert_from_float (
+            (BablFormat *) BABL (babl->fish.destination),
+            (void*) double_buf,
+            (char *) destination,
+            n
+          );
+
+      }
+      else
+      {
+        ncomponent_convert_to_double (
+          (BablFormat *) BABL (babl->fish.source),
+          (char *) source,
+          double_buf,
+          n
+        );
+
+        ncomponent_convert_from_double (
+          (BablFormat *) BABL (babl->fish.destination),
+          double_buf,
+          (char *) destination,
+          n
+        );
+      }
+    }
+  else
+    {
+      if (BABL (babl->fish.source)->format.type[0]->bits < 32 ||
+          BABL (babl->fish.destination)->format.type[0]->bits < 32)
+      {
+
+      convert_to_float (
         (BablFormat *) BABL (babl->fish.source),
         (char *) source,
         double_buf,
         n
       );
 
-      ncomponent_convert_from_double (
+      convert_from_float (
         (BablFormat *) BABL (babl->fish.destination),
         double_buf,
         (char *) destination,
         n
       );
-    }
-  else
-    {
+
+      }
+      else
+      {
+
       convert_to_double (
         (BablFormat *) BABL (babl->fish.source),
         (char *) source,
@@ -436,6 +698,8 @@ process_same_model (const Babl  *babl,
         (char *) destination,
         n
       );
+
+      }
     }
   babl_free (double_buf);
 }
index 750d8366f1dd1dae537fd967852324f023ae73fc..4a09f3e21046a31d70fa143191bcfc517058304a 100644 (file)
@@ -57,6 +57,31 @@ convert_float_double (BablConversion *conversion,
     }
 }
 
+static long
+convert_float_float (const Babl *babl,
+                     char       *src,
+                     char       *dst,
+                     int         src_pitch,
+                     int         dst_pitch,
+                     long        n)
+{
+  if (src_pitch == 32 &&
+      dst_pitch == 32)
+    {
+      memcpy (dst, src, n / 4);
+      return n;
+    }
+
+  while (n--)
+    {
+      (*(float *) dst) = (*(float *) src);
+      dst              += dst_pitch;
+      src              += src_pitch;
+    }
+  return n;
+}
+
+
 void
 babl_base_type_float (void)
 {
@@ -79,4 +104,11 @@ babl_base_type_float (void)
     "plane", convert_double_float,
     NULL
   );
+
+  babl_conversion_new (
+    babl_type_from_id (BABL_FLOAT),
+    babl_type_from_id (BABL_FLOAT),
+    "plane", convert_float_float,
+    NULL
+  );
 }
index 68a99bcc5d6d01bd0ea6f1319d0f76a66e8e1019..6841c9bf8269674b6808cff52748ab3b8bad92ce 100644 (file)
@@ -112,8 +112,8 @@ MAKE_CONVERSIONS (u16, 0.0, 1.0, 0, UINT16_MAX)
 
 static inline void
 convert_float_u16_scaled (BablConversion *conversion,
-                          float    min_val,
-                          float    max_val,
+                          double    min_val,
+                          double    max_val,
                           uint16_t min,
                           uint16_t max,
                           char    *src,
@@ -142,8 +142,8 @@ convert_float_u16_scaled (BablConversion *conversion,
 
 static inline void
 convert_u16_float_scaled (BablConversion *conversion,
-                          float   min_val,
-                          float   max_val,
+                          double   min_val,
+                          double   max_val,
                           uint16_t min,
                           uint16_t max,
                           char    *src,
index 1cf0629bc7cd521cd497d95892f4cd745a7e0213..2ad561bf3b6ec3af45f221d8cc08d056c644ecb4 100644 (file)
@@ -115,8 +115,8 @@ MAKE_CONVERSIONS (u8_chroma, -0.5, 0.5, 16, 240)
 
 static inline void
 convert_float_u8_scaled (BablConversion *c,
-                         float        min_val,
-                         float        max_val,
+                         double        min_val,
+                         double        max_val,
                          unsigned char min,
                          unsigned char max,
                          char         *src,
@@ -145,8 +145,8 @@ convert_float_u8_scaled (BablConversion *c,
 
 static inline void
 convert_u8_float_scaled (BablConversion *c,
-                          float        min_val,
-                          float        max_val,
+                          double        min_val,
+                          double        max_val,
                           unsigned char min,
                           unsigned char max,
                           char         *src,