BABL fish path patch

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

 



Hi,
 attached is a patch that ports BablFishPath class to the
 new list API and the list API is a bit expanded.
 Further, the algorithm for generating the shortest
 conversion path is reformulated to be more readable and
 comprehensible and thoroughly commented. The algorithm for
 processing the conversion paths is reformulated and
 commented. The patch also contains minor readability
 cleanups end speedups.

 Regards,
   Jan

Index: babl/babl-list.c
===================================================================
--- babl/babl-list.c	(revision 300)
+++ babl/babl-list.c	(working copy)
@@ -63,29 +63,78 @@ int
 babl_list_size (BablList *list)
 {
     babl_assert (list);
+
     return list->count;
 }
 
-void
-babl_list_insert (BablList *list,
-                  Babl     *item)
+inline void
+babl_list_insert_last (BablList *list,
+                       Babl     *item)
 {
   babl_assert(list);
   babl_assert(BABL_IS_BABL(item));
 
   if (list->size < list->count + 1)
     {
-        Babl **new_items;
+      Babl **new_items;
 
-        new_items = babl_realloc (list->items, (list->size * 2) * sizeof (BablInstance *));
-        babl_assert (new_items);
-        list->items = new_items;
-        memset (list->items + list->size, 0, list->size * sizeof (BablInstance *));
-        list->size *= 2;
+      new_items = babl_realloc (list->items, (list->size * 2) * sizeof (BablInstance *));
+      babl_assert (new_items);
+      list->items = new_items;
+      memset (list->items + list->size, 0, list->size * sizeof (BablInstance *));
+      list->size *= 2;
     }
     list->items[list->count++] = item;
 }
 
+inline void
+babl_list_remove_last (BablList *list)
+{
+  babl_assert (list);
+  babl_assert (list->count > 0);
+
+  list->count--;
+}
+
+inline Babl *
+babl_list_get_first (BablList *list)
+{
+  babl_assert (list);
+  babl_assert (list->count > 0);
+
+  return (list->items[0]);
+}
+
+inline Babl *
+babl_list_get_last (BablList *list)
+{
+  babl_assert (list);
+  babl_assert (list->count > 0);
+
+  return (list->items[list->count - 1]);
+}
+
+inline void 
+babl_list_copy (BablList *from,
+                BablList *to)
+{
+  babl_assert (from);
+  babl_assert (to);
+
+  if (to->size < from->count)
+    {
+      Babl **new_items;
+
+      new_items = babl_realloc (to->items, from->count * sizeof (BablInstance *));
+      babl_assert (new_items);
+      to->items = new_items;
+      to->size = from->count;
+    }
+
+    memcpy (to->items, from->items, from->count * sizeof (BablInstance *));
+    to->count = from->count;
+}
+
 void
 babl_list_each (BablList         *list,
                 BablEachFunction each_fun,
Index: babl/babl-list.h
===================================================================
--- babl/babl-list.h	(revision 300)
+++ babl/babl-list.h	(working copy)
@@ -47,9 +47,22 @@ babl_list_destroy (BablList *list);
 int
 babl_list_size (BablList *list);
 
-void
-babl_list_insert (BablList *list,
-                  Babl     *item);
+inline void
+babl_list_insert_last (BablList *list,
+                       Babl     *item);
+
+inline void
+babl_list_remove_last (BablList *list);
+
+inline Babl *
+babl_list_get_first (BablList *list);
+
+inline Babl *
+babl_list_get_last (BablList *list);
+
+inline void 
+babl_list_copy (BablList *from,
+                BablList *to);
 
 void
 babl_list_each (BablList      *list,
Index: babl/babl-fish-path.c
===================================================================
--- babl/babl-fish-path.c	(revision 300)
+++ babl/babl-fish-path.c	(working copy)
@@ -19,14 +19,35 @@
 #include <math.h>
 #include "babl-internal.h"
 
+#define BABL_LEGAL_ERROR    0.000001
+#define BABL_MAX_COST_VALUE 2000000
+
 static double
-chain_error (const Babl      *fmt_source,
-             const Babl      *fmt_destination,
-             BablConversion **chain,
-             int              conversions);
+get_conversion_path_error (BablList *path);
+
+static long
+process_conversion_path (BablList *path,
+                         void     *source_buffer,
+                         void     *destination_buffer,
+                         long     n);
+
+static void
+get_conversion_path (Babl *current_format,
+                     int current_length, 
+                     int max_length);
+
+static double *
+test_create (void);
+
+static char *
+create_name (const Babl *source,
+             const Babl *destination,
+             int         is_reference);
+
+static double legal_error (void);
+
+static int max_path_length (void);
 
-//#define BABL_LEGAL_ERROR 0.000001
-//#define BABL_LEGAL_ERROR 0.01
 
 static double legal_error (void)
 {
@@ -40,7 +61,7 @@ static double legal_error (void)
   if (env)
     error = atof (env);
   else
-    error = 0.000001;
+    error = BABL_LEGAL_ERROR;
   return error;
 }
 
@@ -64,207 +85,99 @@ static int max_path_length (void)
   return max_length;
 }
 
-typedef struct BablChainContext
-{
-  const Babl *from;
-  const Babl *to;
 
-  double *best_cost;
-  double *best_loss;
-  double *best_error;
-
-  BablConversion **chain;
-  int             *conversions;
-
-  BablConversion **temp_chain;
-  int              temp_conversions;
-
-  int max_conversions;
-} BablChainContext;
-
-static int
-chain_gen_each (Babl *babl,
-                void *userdata);
-
-static int
-get_conversion_chain (const Babl      *from,
-                      const Babl      *to,
-                      double          *best_cost,
-                      double          *best_loss,
-                      double          *best_error,
-                      BablConversion **chain,
-                      int             *conversions,
-                      BablConversion **temp_chain,
-                      int              temp_conversions,
-                      int              max_conversions)
+/* The task of BablFishPath construction is to compute
+ * the shortest path in a graph where formats are the vertices
+ * and conversions are the edges. However, there is an additional
+ * constraint to the shortest path, that limits conversion error 
+ * introduced by such a path to be less than BABL_ERROR. This
+ * prohibits usage of any reasonable shortest path construction 
+ * algorithm such as Dijkstra's algorithm. The shortest path is
+ * constructed by enumerating all available paths that are less 
+ * than BABL_PATH_LENGTH long, computing their costs and 
+ * conversion errors and backtracking. The backtracking is 
+ * implemented by recursive function get_conversion_path ().
+ */
+
+static Babl *fish_path;
+static Babl *to_format;
+static BablList *current_path;
+
+static void
+get_conversion_path (Babl *current_format,
+                     int current_length, 
+                     int max_length)
 {
-  BablChainContext context;
-
-  if (temp_conversions >= max_conversions)
-    return 0;
-
-  if (temp_conversions == 0)
+  if (current_length > max_length) 
     {
-      /* chain initialization */
-      *conversions  = 0;
-      *best_cost    = 200000.0;
-      *best_loss    = 200000.0;
-      *best_error   = 200000.0;
-      chain[0]      = NULL;
-      temp_chain[0] = NULL;
-
-      /* Bail out if requesting something stupid (to and from same format, an
-       * optimized memcpy should be used instead (assuming linear buffers).
-       */
-
-      if (from == to)
-        return 0;
+      /* We have reached the maximum recursion
+       * depth, let's bail out */
+      return;
     }
+  else if ((current_length > 0) && (current_format == to_format))
+    {
+       /* We have found a candidate path, let's 
+        * see about it's properties */
+      double temp_cost  = 0.0;
+      double temp_error = 1.0;
+      int    i;
 
-  /* copy parameters to stack */
-  context.from = from;
-  context.to   = to;
-
-  context.best_cost   = best_cost;
-  context.best_loss   = best_loss;
-  context.best_error  = best_error;
-  context.chain       = chain;
-  context.conversions = conversions;
-
-  context.temp_chain       = temp_chain;
-  context.temp_conversions = temp_conversions;
-
-  context.max_conversions = max_conversions;
+      for (i = 0; i < babl_list_size (current_path); i++)
+        {
+          temp_error *= (1.0 + babl_conversion_error ((BablConversion *) current_path->items[i]));
+          temp_cost  += babl_conversion_cost ((BablConversion *) current_path->items[i]);
+        }
 
-  if (temp_conversions == 0)
-    {
-      temp_chain[temp_conversions] = NULL;
-      babl_assert (from);
-      babl_assert (from->class_type == BABL_FORMAT);
-      if (!from->format.from_list)
-        return 0;
-
-      babl_list_each (from->format.from_list,
-                      chain_gen_each,
-                      &context);
+      if (temp_cost < fish_path->fish_path.cost &&
+          temp_error - 1.0 <= legal_error () &&     /* check this before the next; 
+                                                       which does a more accurate
+                                                       measurement of the error */
+          (temp_error = get_conversion_path_error (current_path)) <= legal_error ()
+      )
+        {
+          /* We have found the best path so far,
+           * let's copy it into our new fish */
+          fish_path->fish_path.cost = temp_cost;
+          fish_path->fish.error  = temp_error;
+          babl_list_copy (current_path, fish_path->fish_path.conversion_list);
+        }
     }
-  else
+  else 
     {
-      if (BABL (temp_chain[temp_conversions - 1]) &&
-          BABL (temp_chain[temp_conversions - 1]->destination)->
-          format.from_list)
-
-        babl_list_each (
-          BABL (temp_chain[temp_conversions - 1]->destination)->
-          format.from_list,
-          chain_gen_each,
-          &context);
-    }
-
-  return 0;
-}
+      /* 
+       * Bummer, we have to search deeper... */
+      BablList *list;
+      int i;
 
-static int
-chain_contains_fmt (BablConversion **chain,
-                    int              conversions,
-                    const Babl      *fmt)
-{
-  int i;
-
-  for (i = 0; i < conversions; i++)
-    if (BABL (chain[i]->destination) == fmt ||
-        BABL (chain[i]->source) == fmt)
-      {
-        return 1;
-      }
-  return 0;
-}
-
-static int
-chain_gen_each (Babl *babl,
-                void *userdata)
-{
-  BablChainContext *c = userdata;
-
-  /* fill in the conversion for the chain index we are at */
-  c->temp_chain[c->temp_conversions] = (BablConversion *) babl;
+      list = current_format->format.from_list;
+      if (list)
+        {
+          /* Mark the current format in conversion path as visited */
+          current_format->format.visited = 1;
 
-  {
-    if ((BABL (babl->conversion.destination) == c->to))
-      {
-        /* a candidate path has been found */
-
-        double temp_cost  = 0.0;
-        double temp_error = 1.0;
-        int    i;
-
-        for (i = 0; i < c->temp_conversions + 1; i++)
-          {
-            temp_error *= (1.0 + babl_conversion_error (c->temp_chain[i]));
-            temp_cost  += babl_conversion_cost (c->temp_chain[i]);
-          }
-
-        if (temp_cost < *c->best_cost &&
-            temp_error - 1.0 <= legal_error () &&     /* this check before the next; which does a more accurate
-                                                         measurement of the error */
-            (temp_error = chain_error (c->from, c->to, c->temp_chain, c->temp_conversions + 1)) <= legal_error ()
-        )
-          {
-            int i;
-
-            *c->best_cost   = temp_cost;
-            *c->best_error  = temp_error;
-            *c->conversions = c->temp_conversions + 1;
-
-            /* copy from temp chain to best chain */
-            for (i = 0; i < *c->conversions; i++)
-              c->chain[i] = c->temp_chain[i];
-          }
-      }
-    else if (babl->conversion.source != babl->conversion.destination &&
-             !chain_contains_fmt (c->temp_chain,
-                                  c->temp_conversions,
-                                  BABL (babl->conversion.destination)))
-      {
-        /* try to add another conversion level in chain,.. */
-        get_conversion_chain (c->from,      /* irrelevant when recalled */
-                              c->to,
-
-                              c->best_cost,
-                              c->best_loss,
-                              c->best_error,
-                              c->chain,
-                              c->conversions,
+           /* Iterate through unvisited formats from the current format ...*/
+          for (i = 0; i < babl_list_size (list); i++)
+            {
+              Babl *next_conversion = BABL (list->items[i]);
+              Babl *next_format = BABL (next_conversion->conversion.destination);
+              if (!next_format->format.visited)
+                {
+                  /* next_format is not in the current path, we can pay a visit */
+                   babl_list_insert_last (current_path, next_conversion);
+                   get_conversion_path (next_format, current_length + 1, max_length);
+                   babl_list_remove_last (current_path);
+                 }
 
-                              c->temp_chain,
-                              c->temp_conversions + 1,
+            }
 
-                              c->max_conversions);
+          /* Remove the current format from current path */
+          current_format->format.visited = 0;  
+        }
       }
-  }
-  return 0;
-}
-
-static inline Babl *
-assert_conversion_find (void *source,
-                        void *destination)
-{
-  int      i = 0;
-  BablList *conversion_list;
-  Babl     *conversion;
-
-  conversion_list = BABL (source)->type.from_list;
-  for (i = 0; i < babl_list_size (conversion_list); i++)
-    {
-      conversion = BABL (conversion_list->items[i]);
-      if (conversion->conversion.destination == destination)
-        return conversion;
-    }
-  babl_fatal ("failed, aborting");
-  return NULL;
 }
 
 static char buf[1024];
+
 static char *
 create_name (const Babl *source,
              const Babl *destination,
@@ -282,7 +195,6 @@ babl_fish_path (const Babl *source,
 {
   Babl           *babl = NULL;
   char           *name = create_name (source, destination, 1);
-  BablConversion *temp_chain[BABL_HARD_MAX_PATH_LENGTH];
 
   babl = babl_db_exist_by_name (babl_fish_db (), name);
   if (babl) 
@@ -301,39 +213,32 @@ babl_fish_path (const Babl *source,
 
   babl = babl_calloc (1, sizeof (BablFishPath) +
                       strlen (name) + 1);
-  babl->class_type    = BABL_FISH_PATH;
-  babl->instance.id   = 0;
-  babl->instance.name = ((char *) babl) + sizeof (BablFishPath);
-  strcpy (babl->instance.name, name);
-  babl->fish.source      = source;
-  babl->fish.destination = destination;
 
-  babl->fish.processings = 0;
-  babl->fish.pixels      = 0;
-  babl->fish.usecs       = 0;
-  babl->fish.error       = 200000;
-
-  babl->fish_path.cost          = 200000;
-  babl->fish_path.loss          = 200000;
-  babl->fish_path.conversions   = 0;
-  babl->fish_path.conversion[0] = NULL;
+  babl->class_type                = BABL_FISH_PATH;
+  babl->instance.id               = 0;
+  babl->instance.name             = ((char *) babl) + sizeof (BablFishPath);
+  strcpy (babl->instance.name, name);
+  babl->fish.source               = source;
+  babl->fish.destination          = destination;
+  babl->fish.processings          = 0;
+  babl->fish.pixels               = 0;
+  babl->fish.usecs                = 0;
+  babl->fish.error                = BABL_MAX_COST_VALUE;
+  babl->fish_path.cost            = BABL_MAX_COST_VALUE;
+  babl->fish_path.loss            = BABL_MAX_COST_VALUE;
+  babl->fish_path.conversion_list = babl_list_init_with_size (BABL_HARD_MAX_PATH_LENGTH);
+
+  current_path = babl_list_init_with_size (BABL_HARD_MAX_PATH_LENGTH); 
+  fish_path = babl;
+  to_format = (Babl *) destination;
 
-  babl_assert (source->class_type == BABL_FORMAT);
-  babl_assert (destination->class_type == BABL_FORMAT);
+  get_conversion_path ((Babl *) source, 0, max_path_length ());
 
-  get_conversion_chain (source,
-                        destination,
-                        &babl->fish_path.cost,
-                        &babl->fish_path.loss,
-                        &babl->fish.error,
-                        (BablConversion **) (babl->fish_path.conversion),
-                        &babl->fish_path.conversions,
-                        temp_chain,
-                        0,
-                        max_path_length ());
+  babl_list_destroy (current_path);
 
-  if (babl->fish_path.conversions == 0)
+  if (babl_list_size (babl->fish_path.conversion_list) == 0)
     {
+      babl_list_destroy (babl->fish_path.conversion_list);
       babl_free (babl);
       return NULL;
     }
@@ -345,72 +250,6 @@ babl_fish_path (const Babl *source,
   return babl;
 }
 
-static long
-chain_process (BablConversion *chain[],
-               int             conversions,
-               void           *source,
-               void           *destination,
-               long            n)
-{
-  void *bufA = NULL;
-  void *bufB = NULL;
-  int   i;
-
-  babl_assert (source);
-  babl_assert (destination);
-
-  if (conversions > 1)
-    bufA = babl_malloc (n * sizeof (double) * 5);
-  if (conversions > 2)
-    bufB = babl_malloc (n * sizeof (double) * 5);
-
-  for (i = 0; i < conversions; i++)
-    {
-      if (i == 0 && conversions == 1)
-        {
-          babl_conversion_process (BABL (chain[i]),
-                                   source, destination, n);
-        }
-      else if (i == 0)
-        {
-          babl_conversion_process (BABL (chain[i]),
-                                   source, bufA, n);
-        }
-      else if (i % 2 == 0)
-        {
-          if (i + 1 == conversions)
-            {
-              babl_conversion_process (BABL (chain[i]),
-                                       bufB, destination, n);
-            }
-          else
-            {
-              babl_conversion_process (BABL (chain[i]),
-                                       bufB, bufA, n);
-            }
-        }
-      else if (i % 2 == 1)
-        {
-          if (i + 1 == conversions)
-            {
-              babl_conversion_process (BABL (chain[i]),
-                                       bufA, destination, n);
-            }
-          else
-            {
-              babl_conversion_process (BABL (chain[i]),
-                                       bufA, bufB, n);
-            }
-        }
-    }
-  if (bufA)
-    babl_free (bufA);
-  if (bufB)
-    babl_free (bufB);
-
-  return n;
-}
-
 long
 babl_fish_path_process (Babl *babl,
                         void *source,
@@ -422,28 +261,95 @@ babl_fish_path_process (Babl *babl,
   babl_assert (source);
   babl_assert (destination);
 
-  ret = chain_process (babl->fish_path.conversion,
-                       babl->fish_path.conversions,
-                       source,
-                       destination,
-                       n);
+  ret = process_conversion_path (babl->fish_path.conversion_list,
+                                 source,
+                                 destination,
+                                 n);
 
   return ret;
 }
 
+static long
+process_conversion_path (BablList *path,
+                         void     *source_buffer,
+                         void     *destination_buffer,
+                         long     n)
+{
+  int conversions = babl_list_size (path);
 
-#define num_test_pixels  (128 + 16 + 16)
+  if (conversions == 1)
+    {
+      babl_conversion_process (BABL (babl_list_get_first (path)),
+                               source_buffer,
+                               destination_buffer,
+                               n);
+    }
+  else 
+    {
+      void *aux1_buffer = babl_malloc (n * sizeof (double) * 5);
+      void *aux2_buffer = NULL;
+      void *swap_buffer = NULL;
+      int   i;
+
+      if (conversions > 2) 
+        {
+          /* We'll need one more auxiliary buffer */
+          aux2_buffer = babl_malloc (n * sizeof (double) * 5);
+        }
+
+      /* The first conversion goes from source_buffer to aux1_buffer */
+      babl_conversion_process (babl_list_get_first (path),
+                               source_buffer,
+                               aux1_buffer,
+                               n);
+
+      /* Process, if any, conversions between the first and the last 
+       * conversion in the path, in a loop */
+      for (i = 1; i < conversions - 1; i++)
+        {
+          babl_conversion_process (path->items[i],
+                                   aux1_buffer,
+                                   aux2_buffer,
+                                   n);
+          /* Swap the auxiliary buffers */
+          swap_buffer = aux1_buffer;
+          aux1_buffer = aux2_buffer;
+          aux2_buffer = swap_buffer;
+        }
+
+      /* The last conversion goes from aux1_buffer to destination_buffer */
+      babl_conversion_process (babl_list_get_last (path),
+                               aux1_buffer,
+                               destination_buffer,
+                               n);
+
+      /* Free auxiliary buffers */
+      if (aux1_buffer)
+        babl_free (aux1_buffer);
+      if (aux2_buffer)
+        babl_free (aux2_buffer);
+  }
+
+  return n;
+}
+
+#define NUM_TEST_PIXELS  (128 + 16 + 16)
 
 static double *
 test_create (void)
 {
-  double *test;
-  int     i, j;
+  static double test[sizeof (double) * NUM_TEST_PIXELS * 4];
+  static int    flag = 0; 
+  int           i, j;
+
+  /* There is no need to generate the test
+   * more times ... */
+  if (flag)
+    return test;
+  flag = 1;  
 
   srandom (20050728);
 
-  test = babl_malloc (sizeof (double) * num_test_pixels * 4);
-
   /*  add 128 pixels in the valid range between 0.0 and 1.0  */
   for (i = 0; i < 128 * 4; i++)
     test [i] = (double) random () / RAND_MAX;
@@ -460,10 +366,7 @@ test_create (void)
 }
 
 static double
-chain_error (const Babl      *fmt_source,
-             const Babl      *fmt_destination,
-             BablConversion **chain,
-             int              conversions)
+get_conversion_path_error (BablList *path)
 {
   Babl *fmt_rgba_double = babl_format_new (
     babl_model ("RGBA"),
@@ -476,6 +379,9 @@ chain_error (const Babl      *fmt_source
 
   double  error = 0.0;
 
+  Babl   *fmt_source = (Babl *) BABL (babl_list_get_first (path))->conversion.source;
+  Babl   *fmt_destination = (Babl *) BABL (babl_list_get_last (path))->conversion.destination;
+
   double *test;
   void   *source;
   void   *destination;
@@ -492,54 +398,53 @@ chain_error (const Babl      *fmt_source
 
   test = test_create ();
 
-  source                      = babl_calloc (num_test_pixels,
+  source                      = babl_calloc (NUM_TEST_PIXELS,
                                              fmt_source->format.bytes_per_pixel);
-  destination                 = babl_calloc (num_test_pixels,
+  destination                 = babl_calloc (NUM_TEST_PIXELS,
                                              fmt_destination->format.bytes_per_pixel);
-  ref_destination             = babl_calloc (num_test_pixels,
+  ref_destination             = babl_calloc (NUM_TEST_PIXELS,
                                              fmt_destination->format.bytes_per_pixel);
-  destination_rgba_double     = babl_calloc (num_test_pixels,
+  destination_rgba_double     = babl_calloc (NUM_TEST_PIXELS,
                                              fmt_rgba_double->format.bytes_per_pixel);
-  ref_destination_rgba_double = babl_calloc (num_test_pixels,
+  ref_destination_rgba_double = babl_calloc (NUM_TEST_PIXELS,
                                              fmt_rgba_double->format.bytes_per_pixel);
 
   /* create sourcebuffer from testbuffer in the correct format */
   babl_process (fish_rgba_to_source,
-                test, source, num_test_pixels);
+                test, source, NUM_TEST_PIXELS);
 
   /* calculate the reference buffer of how it should be */
   babl_process (fish_reference,
-                source, ref_destination, num_test_pixels);
+                source, ref_destination, NUM_TEST_PIXELS);
 
-  /* calculate this chains view of what the result should be */
-  chain_process (chain, conversions, source, destination, num_test_pixels);
+  /* calculate this path's view of what the result should be */
+  process_conversion_path (path, source, destination, NUM_TEST_PIXELS);
 
   /* transform the reference and the actual destination buffers to RGBA
    * for comparison with each other
    */
   babl_process (fish_destination_to_rgba,
-                ref_destination, ref_destination_rgba_double, num_test_pixels);
+                ref_destination, ref_destination_rgba_double, NUM_TEST_PIXELS);
   babl_process (fish_destination_to_rgba,
-                destination, destination_rgba_double, num_test_pixels);
+                destination, destination_rgba_double, NUM_TEST_PIXELS);
 
   error = babl_rel_avg_error (destination_rgba_double,
                               ref_destination_rgba_double,
-                              num_test_pixels * 4);
+                              NUM_TEST_PIXELS * 4);
 
   fish_rgba_to_source->fish.processings--;
   fish_reference->fish.processings--;
   fish_destination_to_rgba->fish.processings -= 2;
 
-  fish_rgba_to_source->fish.pixels      -= num_test_pixels;
-  fish_reference->fish.pixels           -= num_test_pixels;
-  fish_destination_to_rgba->fish.pixels -= 2 * num_test_pixels;
+  fish_rgba_to_source->fish.pixels      -= NUM_TEST_PIXELS;
+  fish_reference->fish.pixels           -= NUM_TEST_PIXELS;
+  fish_destination_to_rgba->fish.pixels -= 2 * NUM_TEST_PIXELS;
 
   babl_free (source);
   babl_free (destination);
   babl_free (destination_rgba_double);
   babl_free (ref_destination);
   babl_free (ref_destination_rgba_double);
-  babl_free (test);
 
   return error;
 }
Index: babl/babl-classes.h
===================================================================
--- babl/babl-classes.h	(revision 300)
+++ babl/babl-classes.h	(working copy)
@@ -177,6 +177,8 @@ typedef struct
   int              planar;
   double           loss; /*< average relative error when converting
                              from and to RGBA double */
+  int              visited; /* for convenience in code while searching 
+                               for conversion paths */
 } BablFormat;
 
 typedef struct
@@ -241,9 +243,7 @@ typedef struct
   BablFish         fish;
   double           cost;   /* number of  ticks *10 + chain_length */
   double           loss;   /* error introduced */
-
-  int              conversions;
-  BablConversion  *conversion[BABL_HARD_MAX_PATH_LENGTH];
+  BablList         *conversion_list;
 } BablFishPath;
 
 /* BablFishReference
Index: babl/babl-conversion.c
===================================================================
--- babl/babl-conversion.c	(revision 300)
+++ babl/babl-conversion.c	(working copy)
@@ -277,7 +277,7 @@ babl_conversion_new (void *first_arg,
   babl_db_insert (db, babl);
   if (!source->type.from_list)
     source->type.from_list = babl_list_init_with_size (BABL_CONVERSIONS);
-  babl_list_insert (source->type.from_list, babl);  
+  babl_list_insert_last (source->type.from_list, babl);  
   return babl;
 }
 
@@ -474,6 +474,11 @@ babl_conversion_error (BablConversion *c
   if (!conversion)
     return 0.0;
 
+  if (conversion->error != -1.0)  /* double conversion against a set value should work */
+    {
+      return conversion->error;
+    }
+
   fmt_source      = BABL (conversion->source);
   fmt_destination = BABL (conversion->destination);
 
@@ -496,10 +501,6 @@ babl_conversion_error (BablConversion *c
     {
       conversion->error = 0.000042;
     }
-  if (conversion->error != -1.0)  /* double conversion against a set value should work */
-    {
-      return conversion->error;
-    }
 
   test = test_create ();
 
Index: babl/babl-db.c
===================================================================
--- babl/babl-db.c	(revision 300)
+++ babl/babl-db.c	(working copy)
@@ -97,7 +97,7 @@ babl_db_insert (BablDb *db,
   if (item->instance.id)
     babl_hash_table_insert (db->id_hash, item);
   babl_hash_table_insert (db->name_hash, item);
-  babl_list_insert (db->babl_list, item);
+  babl_list_insert_last (db->babl_list, item);
 
   /* this point all registered items pass through, a nice
   * place to brand them with where the item came from. */
Index: babl/babl-fish-stats.c
===================================================================
--- babl/babl-fish-stats.c	(revision 300)
+++ babl/babl-fish-stats.c	(working copy)
@@ -48,7 +48,7 @@ table_destination_each (Babl *babl,
 
             fprintf (output_file, "<td class='cell'%s><a href='javascript:o()'>%s",
                      fish->fish.processings > 0 ? " style='background-color: #69f'" : "",
-                     utf8_bar[fish->fish_path.conversions]);
+                     utf8_bar[babl_list_size (fish->fish_path.conversion_list)]);
 
             {
               int i;
@@ -68,12 +68,14 @@ table_destination_each (Babl *babl,
               fprintf (output_file, "<td style='text-align:right'><em>error</em></td>");
               fprintf (output_file, "</tr>");
 
-              for (i = 0; i < fish->fish_path.conversions; i++)
+              for (i = 0; i < babl_list_size (fish->fish_path.conversion_list); i++)
                 {
                   fprintf (output_file, "<tr>");
-                  fprintf (output_file, "<td>%s</td>", BABL (fish->fish_path.conversion[i])->instance.name);
-                  fprintf (output_file, "<td class='r'>%li</td>", babl_conversion_cost (&BABL (fish->fish_path.conversion[i])->conversion));
-                  fprintf (output_file, "<td class='r'>%e</td>", babl_conversion_error (&BABL (fish->fish_path.conversion[i])->conversion));
+                  fprintf (output_file, "<td>%s</td>", BABL (fish->fish_path.conversion_list->items[i])->instance.name);
+                  fprintf (output_file, "<td class='r'>%li</td>", 
+                    babl_conversion_cost (&BABL (fish->fish_path.conversion_list->items[i])->conversion));
+                  fprintf (output_file, "<td class='r'>%e</td>", 
+                    babl_conversion_error (&BABL (fish->fish_path.conversion_list->items[i])->conversion));
                   fprintf (output_file, "</tr>");
                 }
 
Index: babl/babl-fish.c
===================================================================
--- babl/babl-fish.c	(revision 300)
+++ babl/babl-fish.c	(working copy)
@@ -213,6 +213,8 @@ static int
 each_babl_fish_destroy (Babl *babl,
                         void *data)
 {
+  if (babl->class_type == BABL_FISH_PATH)
+    babl_list_destroy (babl->fish_path.conversion_list);
   babl_free (babl);
   return 0;  /* continue iterating */
 }
Index: tests/babl_fish_path_fitness.c
===================================================================
--- tests/babl_fish_path_fitness.c	(revision 300)
+++ tests/babl_fish_path_fitness.c	(working copy)
@@ -43,8 +43,8 @@ static int destination_each (Babl *babl,
 
       if (temp)
         {
-          printf ("%s", utf8_bar[temp->fish_path.conversions]);
-          total_length += temp->fish_path.conversions;
+          printf ("%s", utf8_bar[babl_list_size (temp->fish_path.conversion_list)]);
+          total_length += babl_list_size (temp->fish_path.conversion_list);
           total_cost   += temp->fish_path.cost;
           ok++;
           total++;
_______________________________________________
Gegl-developer mailing list
Gegl-developer@xxxxxxxxxxxxxxxxxxxxxx
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer

[Index of Archives]     [Yosemite News]     [Yosemite Photos]     [gtk]     [GIMP Users]     [KDE]     [Gimp's Home]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux