[babl] palette: add capability to use palette formats with separate alpha



commit 9d2aa7d13ac421935de1e87301c48af50b0ceb59
Author: Ãyvind KolÃs <pippin gimp org>
Date:   Sat Mar 17 17:02:44 2012 +0000

    palette: add capability to use palette formats with separate alpha
    
    Also refactored to make babl-palette.c only use public API.

 babl/babl-fish-path.c |    6 +-
 babl/babl-format.c    |   14 +++
 babl/babl-ids.h       |    1 -
 babl/babl-palette.c   |  226 +++++++++++++++++++++++++++++++++++--------------
 babl/babl.h           |   18 ++++-
 tests/palette.c       |   39 ++++++++-
 6 files changed, 230 insertions(+), 74 deletions(-)
---
diff --git a/babl/babl-fish-path.c b/babl/babl-fish-path.c
index c7caa35..a2d1a68 100644
--- a/babl/babl-fish-path.c
+++ b/babl/babl-fish-path.c
@@ -287,7 +287,8 @@ babl_fish_path (const Babl *source,
     pc.fish_path = babl;
     pc.to_format = (Babl *) destination;
 
-    babl_mutex_lock (babl_format_mutex);
+    if (babl_in_fish_path <= 0)
+      babl_mutex_lock (babl_format_mutex);
     /* we hold a global lock whilerunning get_conversion_path since
      * it depends on keeping the various format.visited members in
      * a consistent state, this code path is not performance critical
@@ -298,7 +299,8 @@ babl_fish_path (const Babl *source,
     get_conversion_path (&pc, (Babl *) source, 0, max_path_length ());
 
     babl_in_fish_path--;
-    babl_mutex_unlock (babl_format_mutex);
+    if (babl_in_fish_path <= 0)
+      babl_mutex_unlock (babl_format_mutex);
     babl_free (pc.current_path);
   }
 
diff --git a/babl/babl-format.c b/babl/babl-format.c
index d95384e..21d33e9 100644
--- a/babl/babl-format.c
+++ b/babl/babl-format.c
@@ -619,4 +619,18 @@ babl_format_loss (Babl *babl)
   return loss;
 }
 
+
+void *
+babl_get_user_data (Babl *babl)
+{
+  return babl->format.model->data;
+}
+
+void
+babl_set_user_data (Babl *babl, void *data)
+{
+  babl->format.model_data = data;
+  babl->format.model->data = babl->format.model_data;
+}
+
 BABL_CLASS_IMPLEMENT (format)
diff --git a/babl/babl-ids.h b/babl/babl-ids.h
index f26add8..f0f6c61 100644
--- a/babl/babl-ids.h
+++ b/babl/babl-ids.h
@@ -85,7 +85,6 @@ enum {
   BABL_CB,
   BABL_CR,
   BABL_PADDING,
-  BABL_PAL,
   BABL_COMPONENT_LAST_INTERNAL,
 
   BABL_FORMAT_BASE = 100000,
diff --git a/babl/babl-palette.c b/babl/babl-palette.c
index c8f10d0..9fc525a 100644
--- a/babl/babl-palette.c
+++ b/babl/babl-palette.c
@@ -16,17 +16,10 @@
  * <http://www.gnu.org/licenses/>.
  */
 
-#include "config.h"
 #include <stdlib.h>
-
-#include "babl-internal.h"
-#include "babl-classes.h"
+#include <string.h>
+#include <stdio.h>
 #include "babl.h"
-#include "babl-ids.h"
-#include "util.h"
-#include "rgb-constants.h"
-#include "math.h"
-#include "babl-base.h"
 
 typedef struct BablPalette
 {
@@ -40,10 +33,10 @@ static BablPalette *make_pal (Babl *format, void *data, int count)
 {
   BablPalette *pal = NULL;
   int bpp = babl_format_get_bytes_per_pixel (format);
-  pal = babl_malloc (sizeof (BablPalette));
+  pal = malloc (sizeof (BablPalette));
   pal->count = count;
   pal->format = format;
-  pal->data = babl_malloc (bpp * count);
+  pal->data = malloc (bpp * count);
   memcpy (pal->data, data, bpp * count);
   return pal;
 }
@@ -67,7 +60,6 @@ static unsigned char defpal_data[4*16] =
 0  ,255,255,255,
 255,255,255,255,
 };
-
 static BablPalette *default_palette (void)
 {
   static BablPalette pal;
@@ -76,7 +68,10 @@ static BablPalette *default_palette (void)
     return &pal;
   inited = 1;
   pal.count = 16;
-  pal.format = babl_format ("RGBA u8");
+  pal.format = babl_format ("RGBA u8"); /* dynamically generated, so
+                                           the default palette can
+                                           not be fully static.
+                                         */
   pal.data = defpal_data;
   return &pal;
 }
@@ -92,13 +87,9 @@ rgba_to_pal (char *src,
   Babl        *fish;
   int bpp;
   
-  if (babl_in_fish_path)
-    babl_mutex_unlock (babl_format_mutex);
   fish = babl_fish (
       pal->format,
-      babl_format_from_id (BABL_RGBA_DOUBLE));
-  if (babl_in_fish_path)
-    babl_mutex_lock (babl_format_mutex);
+      babl_format ("RGBA double"));
 
   bpp = babl_format_get_bytes_per_pixel (pal->format);
   while (n--)
@@ -140,6 +131,63 @@ rgba_to_pal (char *src,
 }
 
 static long
+rgba_to_pala (char *src,
+              char *dst,
+              long  n,
+              void *foo,
+              void *dst_model_data)
+{
+  BablPalette *pal = dst_model_data;
+  Babl        *fish;
+  int bpp;
+  
+  fish = babl_fish (
+      pal->format,
+      babl_format ("RGBA double"));
+
+  bpp = babl_format_get_bytes_per_pixel (pal->format);
+
+  while (n--)
+    {
+      int idx;
+
+      int best_idx = 0;
+      double best_diff = 100000;
+      double *srcf;
+      double alpha;
+
+      srcf = ((double *) src);
+      alpha = srcf[3];
+
+      for (idx = 0; idx<pal->count; idx++)
+        {
+          double diff;
+          double palpx[4];
+
+          /* oh horror, at least cache the format */
+          babl_process (fish, ((char*)pal->data) + idx * bpp,
+                palpx, 1);
+
+          diff = (palpx[0] - srcf[0]) * (palpx[0] - srcf[0]) +
+                 (palpx[1] - srcf[1]) * (palpx[1] - srcf[1]) +
+                 (palpx[2] - srcf[2]) * (palpx[2] - srcf[2]);
+          if (diff < best_diff)
+            {
+              best_diff = diff;
+              best_idx = idx;
+            }
+        }
+
+      ((double *) dst)[0] = best_idx / 256.0;
+      ((double *) dst)[1] = alpha;
+
+      src += sizeof (double) * 4;
+      dst += sizeof (double) * 2;
+    }
+  return n;
+}
+
+static long
 pal_to_rgba (char *src,
              char *dst,
              long  n,
@@ -149,14 +197,13 @@ pal_to_rgba (char *src,
   BablPalette *pal = src_model_data;
   Babl        *fish = babl_fish (
       pal->format,
-      babl_format_from_id (BABL_RGBA_DOUBLE));
+      babl_format ("RGBA double"));
   int bpp = babl_format_get_bytes_per_pixel (pal->format);
 
   while (n--)
     {
-      int    idx;
+      int idx      = (((double *) src)[0]) * 256.0;
 
-      idx       = (((double *) src)[0]) * 256.0;
 
       if (idx < 0) idx = 0;
       if (idx >= pal->count) idx = pal->count-1;
@@ -171,7 +218,42 @@ pal_to_rgba (char *src,
   return n;
 }
 
-Babl *babl_new_palette (const char *name)
+
+static long
+pala_to_rgba (char *src,
+              char *dst,
+              long  n,
+              void *src_model_data,
+              void *foo)
+{
+  BablPalette *pal = src_model_data;
+  Babl        *fish = babl_fish (
+      pal->format,
+      babl_format ("RGBA double"));
+  int bpp = babl_format_get_bytes_per_pixel (pal->format);
+
+  while (n--)
+    {
+      int idx      = (((double *) src)[0]) * 256.0;
+      double alpha = (((double *) src)[1]);
+
+
+      if (idx < 0) idx = 0;
+      if (idx >= pal->count) idx = pal->count-1;
+
+      babl_process (fish, 
+            ((char*)pal->data) + idx * bpp,
+            dst, 1);
+
+      ((double *)dst)[3] *= alpha; 
+
+      src += sizeof (double) * 2;
+      dst += sizeof (double) * 4;
+    }
+  return n;
+}
+
+Babl *babl_new_palette (const char *name, int with_alpha)
 {
   Babl *model;
   Babl *format;
@@ -180,46 +262,69 @@ Babl *babl_new_palette (const char *name)
   if (!name)
     {
       static int cnt = 0;
-      sprintf (cname, "pal-%i", cnt++);
+      sprintf (cname, "_babl-int-%i", cnt++);
       name = cname;
     }
 
+  /* re-registering is a no-op */
   babl_component_new (
     "I",
-    "id", BABL_PAL,
     "luma",
     "chroma",
     "alpha",
     NULL);
   
-  model = babl_model_new (
-    "name", name,
-    babl_component_from_id (BABL_PAL),
-    NULL);
   
-  model->model.data = (void*) 0x012;
-
-  babl_conversion_new (
-    model,
-    babl_model_from_id (BABL_RGBA),
-    "linear", pal_to_rgba,
-    NULL
-  );
-
-  babl_conversion_new (
-    babl_model_from_id (BABL_RGBA),
-    model,
-    "linear", rgba_to_pal,
-    NULL
-  );
-
-  format = babl_format_new ("name", name, model,
-                            babl_type ("u8"),
-                            babl_component ("I"), NULL);
-
-  format->format.model_data = default_palette ();
-  format->format.model->data = format->format.model_data;
+  if (with_alpha)
+    {
+      model = babl_model_new ("name", name,
+                              babl_component ("I"),
+                              babl_component ("A"),
+                              NULL);
+      format = babl_format_new ("name", name, model,
+                                babl_type ("u8"),
+                                babl_component ("I"),
+                                babl_component ("A"),
+                                NULL);
+
+      babl_conversion_new (
+        model,
+        babl_model  ("RGBA"),
+        "linear", pala_to_rgba,
+        NULL
+      );
+
+      babl_conversion_new (
+        babl_model  ("RGBA"),
+        model,
+        "linear", rgba_to_pala,
+        NULL
+      );
+    }
+  else
+    {
+      model = babl_model_new ("name", name,
+                              babl_component ("I"),
+                              NULL);
+      babl_conversion_new (
+        model,
+        babl_model ("RGBA"),
+        "linear", pal_to_rgba,
+        NULL
+      );
+
+      babl_conversion_new (
+        babl_model ("RGBA"),
+        model,
+        "linear", rgba_to_pal,
+        NULL
+      );
+      format = babl_format_new ("name", name, model,
+                                babl_type ("u8"),
+                                babl_component ("I"), NULL);
+    }
 
+  babl_set_user_data (format, default_palette ());
   babl_sanity ();
   return format;
 }
@@ -230,25 +335,18 @@ babl_palette_set_palette (Babl *babl,
                           void *data,
                           int   count)
 {
-  if (babl->format.model->data != default_palette ())
-    {
-      BablPalette *pal = babl->format.model->data;
-      babl_free (pal->data);
-      babl_free (pal);
-    }
-  babl->format.model_data = make_pal (format, data, count);
-  babl->format.model->data = babl->format.model_data;
+  babl_palette_reset (babl);
+  babl_set_user_data (babl, make_pal (format, data, count));
 }
 
 void
 babl_palette_reset (Babl *babl)
 {
-  if (babl->format.model->data != default_palette ())
+  if (babl_get_user_data (babl) != default_palette ())
     {
-      BablPalette *pal = babl->format.model->data;
-      babl_free (pal->data);
-      babl_free (pal);
+      BablPalette *pal = babl_get_user_data (babl);
+      free (pal->data);
+      free (pal);
     }
-  babl->format.model_data = default_palette ();
-  babl->format.model->data = babl->format.model_data;
+  babl_set_user_data (babl, default_palette ());
 }
diff --git a/babl/babl.h b/babl/babl.h
index e4b0082..57b2895 100644
--- a/babl/babl.h
+++ b/babl/babl.h
@@ -202,9 +202,10 @@ Babl * babl_conversion_new (void *first_arg,
 
 /**
  * create a new palette based format, name is optional pass in NULL to get
- * an anonymous format.
+ * an anonymous format. If you pass in with_alpha the format also gets
+ * an 8bit alpha channel.
  */
-Babl *babl_new_palette         (const char *name);
+Babl *babl_new_palette         (const char *name, int with_alpha);
 
 /**
  * Assign a palette to a palette format, the data is a single span of pixels
@@ -221,6 +222,19 @@ void  babl_palette_set_palette (Babl              *babl,
 void  babl_palette_reset       (Babl              *babl);
 
 
+/**
+ * associate a data pointer with a format/model, this data can be accessed and
+ * used from the conversion functions, encoding color profiles, palettes or
+ * similar with the data.
+ */
+void   babl_set_user_data     (Babl *babl, void *data);
+
+/**
+ * get data set with babl_set_user_data
+ */
+void * babl_get_user_data     (Babl *babl);
+
+
 
 /*
  * Backwards compatibility stuff
diff --git a/tests/palette.c b/tests/palette.c
index 02f79ac..afd52f9 100644
--- a/tests/palette.c
+++ b/tests/palette.c
@@ -58,8 +58,8 @@ main (int    argc,
   {
     unsigned char in[][1]   = {{        0},{          1},{          2},{15}};
     unsigned char out[][4]  = {{0,0,0,255},{127,0,0,255},{0,127,0,255},{255,255,255,255}};
-    Babl *palA = babl_new_palette (NULL);
-    Babl *palB = babl_new_palette (NULL);
+    Babl *palA = babl_new_palette (NULL, 0);
+    Babl *palB = babl_new_palette (NULL, 0);
 
     CHECK_CONV("pal to rgba", unsigned char,
         palA, babl_format("RGBA u8"),
@@ -79,7 +79,16 @@ main (int    argc,
     unsigned char out[][1] = {{        0},{          1},{          2}};
 
     CHECK_CONV("rgba to pal", unsigned char,
-         babl_format("RGBA u8"), babl_new_palette ("palC"),
+         babl_format("RGBA u8"), babl_new_palette ("palC", 0),
+         in, out);
+  }
+
+  {
+    unsigned char in[][4]  = {{0,0,0,255},{140,0,0,255},{0,127,0,127}};
+    unsigned char out[][2] = {{    0,255},{      1,255},{      2,127}};
+
+    CHECK_CONV("rgba to pal+alpha", unsigned char,
+         babl_format("RGBA u8"), babl_new_palette ("palD", 1),
          in, out);
   }
 
@@ -91,10 +100,10 @@ main (int    argc,
       1.0,  0.2
     };
 
-    unsigned char in[][1]   = {{         0},{          1},{          2}};
+    unsigned char in[][1]   = {{              0},{          1},{          2}};
     unsigned char out[][4]  = {{128,128,128,255},{59,59,59,107},{255,255,255,51}};
 
-    Babl *pal = babl_new_palette (NULL);
+    Babl *pal = babl_new_palette (NULL, 0);
 
     babl_palette_set_palette (pal, babl_format ("YA float"), palette, 3);
 
@@ -103,6 +112,26 @@ main (int    argc,
          in, out);
   }
 
+  /* check with a custom floating point palette, _and_ alpha component  */
+  {
+    float palette[] = {
+      0.5,  1.0,
+      0.23, 0.42,
+      1.0,  0.2
+    };
+
+    unsigned char in[][2]   = {{          0,255},{0,127},{       1,255},{         2,255}};
+    unsigned char out[][4]  = {{128,128,128,255},{128,128,128,127},{59,59,59,107},{255,255,255,51}};
+
+    Babl *pal = babl_new_palette (NULL, 1);
+
+    babl_palette_set_palette (pal, babl_format ("YA float"), palette, 3);
+
+    CHECK_CONV("rgba to YA float pal+alpha", unsigned char,
+         pal, babl_format("RGBA u8"),
+         in, out);
+  }
+
   babl_exit ();
   return !OK;
 }



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