[babl] babl-icc: create struct for abstracting ICC file access



commit 1d31fd12c0edaa3d21e2fb53e56ebf613cc9dee5
Author: Øyvind Kolås <pippin gimp org>
Date:   Wed Aug 23 19:53:43 2017 +0200

    babl-icc: create struct for abstracting ICC file access
    
    This also makes the ICC parsing re-entrant by getting rid of global variables.

 babl/babl-icc.c      |  349 +++++++++++++++++++++++++++-----------------------
 babl/babl-internal.h |    9 +-
 babl/babl-trc.c      |   19 ++-
 babl/babl-trc.h      |   22 +++-
 babl/babl.h          |    5 +-
 5 files changed, 233 insertions(+), 171 deletions(-)
---
diff --git a/babl/babl-icc.c b/babl/babl-icc.c
index 2c6a2a0..69f0df0 100644
--- a/babl/babl-icc.c
+++ b/babl/babl-icc.c
@@ -21,6 +21,31 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+typedef struct ICC {
+  char *data;
+  int   length;
+
+  int   tags;
+  int   headpos;
+  int   o, no;
+  int   p;
+  int   psize;
+} ICC;
+
+ICC *icc_state_new (char *data, int length, int tags);
+
+ICC *icc_state_new (char *data, int length, int tags)
+{
+  ICC *ret = babl_calloc (sizeof (ICC), 1);
+  ret->data = data;
+  ret->length = length;
+  ret->tags = tags;
+
+  return ret;
+}
+
+
+
 #define ICC_HEADER_LEN 128
 #define TAG_COUNT_OFF  ICC_HEADER_LEN
 
@@ -38,81 +63,81 @@ typedef struct {
   char str[5];
 } sign_t;
 
-#define icc_write(type, offset, value)  write_##type(icc,length,offset,value)
-#define icc_read(type, offset)          read_##type(icc,length,offset)
+#define icc_write(type, offset, value)  write_##type(state,offset,value)
+#define icc_read(type, offset)          read_##type(state,offset)
 
-static void write_u8 (char *icc, int length, int offset, uint8_t value)
+static void write_u8 (ICC *state, int offset, uint8_t value)
 {
-  if (offset < 0 || offset > length)
+  if (offset < 0 || offset >= state->length)
     return;
-  *(uint8_t*) (&icc[offset]) = value;
+  *(uint8_t*) (&state->data[offset]) = value;
 }
 
-static void write_s8 (char *icc, int length, int offset, int8_t value)
+static void write_s8 (ICC *state, int offset, int8_t value)
 {
-  if (offset < 0 || offset > length)
+  if (offset < 0 || offset >= state->length)
     return;
-  *(int8_t*) (&icc[offset]) = value;
+  *(int8_t*) (&state->data[offset]) = value;
 }
 
-static int read_u8 (const char *icc, int length, int offset)
+static int read_u8 (ICC *state, int offset)
 {
 /* all reading functions take both the char *pointer and the length of the
  * buffer, and all reads thus gets protected by this condition.
  */
-  if (offset < 0 || offset > length)
+  if (offset < 0 || offset > state->length)
     return 0;
 
-  return *(uint8_t*) (&icc[offset]);
+  return *(uint8_t*) (&state->data[offset]);
 }
 
-static int read_s8 (const char *icc, int length, int offset)
+static int read_s8 (ICC *state, int offset)
 {
-  if (offset < 0 || offset > length)
+  if (offset < 0 || offset > state->length)
     return 0;
 
-  return *(int8_t*) (&icc[offset]);
+  return *(int8_t*) (&state->data[offset]);
 }
 
-static void write_s16 (char *icc, int length, int offset, int16_t value)
+static void write_s16 (ICC *state, int offset, int16_t value)
 {
-  write_s8 (icc, length, offset + 0, value >> 8);
-  write_u8 (icc, length, offset + 1, value & 0xff);
+  write_s8 (state, offset + 0, value >> 8);
+  write_u8 (state, offset + 1, value & 0xff);
 }
 
-static int16_t read_s16 (const char *icc, int length, int offset)
+static int16_t read_s16 (ICC *state, int offset)
 {
   return icc_read (u8, offset + 1) +
-         (read_s8 (icc, length, offset + 0) << 8);
+         (read_s8 (state, offset + 0) << 8); //XXX: transform to icc_read macro
 }
 
-static uint16_t read_u16 (const char *icc, int length, int offset)
+static uint16_t read_u16 (ICC *state, int offset)
 {
   return icc_read (u8, offset + 1) +
          (icc_read (u8, offset + 0) << 8);
 }
 
-static void write_u16 (char *icc, int length, int offset, uint16_t value)
+static void write_u16 (ICC *state, int offset, uint16_t value)
 {
-  write_u8 (icc, length, offset + 0, value >> 8);
-  write_u8 (icc, length, offset + 1, value & 0xff);
+  write_u8 (state, offset + 0, value >> 8);
+  write_u8 (state, offset + 1, value & 0xff);
 }
 
-static u8f8_t read_u8f8_ (const char *icc, int length, int offset)
+static u8f8_t read_u8f8_ (ICC *state, int offset)
 {
   u8f8_t ret ={icc_read (u8, offset),
                icc_read (u8, offset + 1)};
   return ret;
 }
 
-static s15f16_t read_s15f16_ (const char *icc, int length, int offset)
+static s15f16_t read_s15f16_ (ICC *state, int offset)
 {
   s15f16_t ret ={icc_read (s16, offset),
                  icc_read (u16, offset + 2)};
   return ret;
 }
 
-static void write_s15f16_ (char *icc, int length, int offset, s15f16_t val)
+static void write_s15f16_ (ICC *state, int offset, s15f16_t val)
 {
   icc_write (s16, offset, val.integer),
   icc_write (u16, offset + 2, val.fraction);
@@ -136,19 +161,19 @@ static double u8f8_to_d (u8f8_t fix)
   return fix.integer + fix.fraction / 255.0;
 }
 
-static void write_s15f16 (char *icc, int length, int offset, double value)
+static void write_s15f16 (ICC *state, int offset, double value)
 {
-   write_s15f16_ (icc, length, offset, d_to_s15f16 (value));
+   write_s15f16_ (state, offset, d_to_s15f16 (value));
 }
 
-static double read_s15f16 (const char *icc, int length, int offset)
+static double read_s15f16 (ICC *state, int offset)
 {
-  return s15f16_to_d (read_s15f16_ (icc, length, offset));
+  return s15f16_to_d (read_s15f16_ (state, offset));
 }
 
-static double read_u8f8 (const char *icc, int length, int offset)
+static double read_u8f8 (ICC *state, int offset)
 {
-  return u8f8_to_d (read_u8f8_ (icc, length, offset));
+  return u8f8_to_d (read_u8f8_ (state, offset));
 }
 
 static inline void print_u8f8 (u8f8_t fix)
@@ -195,22 +220,19 @@ static inline void print_s15f16 (s15f16_t fix)
   }
 }
 
-static void write_u32 (char *icc,
-                      int length,
-                      int offset,
-                      uint32_t value)
+static void write_u32 (ICC *state, int offset, uint32_t value)
 {
   int i;
   for (i = 0; i < 4; i ++)
   {
-    write_u8 (icc, length, offset + i,
+    write_u8 (state, offset + i,
                   (value & 0xff000000) >> 24
                   );
     value <<= 8;
   }
 }
 
-static uint32_t read_u32 (const char *icc, int length, int offset)
+static uint32_t read_u32 (ICC *state, int offset)
 {
   return icc_read (u8, offset + 3) +
          (icc_read (u8, offset + 2) << 8) +
@@ -218,8 +240,7 @@ static uint32_t read_u32 (const char *icc, int length, int offset)
          (icc_read (u8, offset + 0) << 24);
 }
 
-static sign_t read_sign (const char *icc, int length,
-                         int offset)
+static sign_t read_sign (ICC *state, int offset)
 {
   sign_t ret;
   ret.str[0]=icc_read (u8, offset);
@@ -230,8 +251,7 @@ static sign_t read_sign (const char *icc, int length,
   return ret;
 }
 
-static void write_sign (char *icc, int length,
-                       int offset, char *sign)
+static void write_sign (ICC *state, int offset, const char *sign)
 {
   int i;
   for (i = 0; i < 4; i ++)
@@ -240,7 +260,7 @@ static void write_sign (char *icc, int length,
 
 /* looks up offset and length for a specific icc tag
  */
-static int icc_tag (const char *icc, int length,
+static int icc_tag (ICC *state,
                     const char *tag, int *offset, int *el_length)
 {
   int tag_count = icc_read (u32, TAG_COUNT_OFF);
@@ -261,11 +281,9 @@ static int icc_tag (const char *icc, int length,
   return 0;
 }
 
-static const Babl *babl_trc_from_icc (const char *icc,
-                                      int         length,
-                                      char      **error)
+static const Babl *babl_trc_from_icc (ICC  *state, int offset,
+                                      char **error)
 {
-  int offset = 0;
   {
     int count = icc_read (u32, offset + 8);
     int i;
@@ -280,8 +298,7 @@ static const Babl *babl_trc_from_icc (const char *icc,
       }
       else
       {
-        return babl_trc_gamma (2.2);
-
+        return babl_trc_gamma (10.0);
         // XXX: todo implement a curve trc babl type
         //      as well as detect sRGB curve from LUTs
 
@@ -297,15 +314,33 @@ static const Babl *babl_trc_from_icc (const char *icc,
   return NULL;
 }
 
+static void icc_allocate_tag (ICC *state, const char *tag, int size)
+{
+    state->no+=((4-state->o)%4);state->o = state->no;state->psize = size;
+    icc_write (sign, 128 + 4 + 4 * state->headpos++, tag);
+    icc_write (u32,  128 + 4 + 4 * state->headpos++, state->o);
+    icc_write (u32,  128 + 4 + 4 * state->headpos++, size);
+    state->p = state->no;\
+    state->no+=size;
+}
+
+static void icc_duplicate_tag(ICC *state, const char *tag)
+{
+    icc_write (sign, 128 + 4 + 4 * state->headpos++, tag);
+    icc_write (u32,  128 + 4 + 4 * state->headpos++, state->p);
+    icc_write (u32,  128 + 4 + 4 * state->headpos++, state->psize);
+}
 
 const char *babl_space_rgb_to_icc (const Babl *babl, int *ret_length)
 {
   const BablSpace *space = &babl->space;
   static char icc[8192];
   int length=4095;
+  ICC *state = icc_state_new (icc, length, 10);
+
   icc[length]=0;
 
-#if 1
+#if 0
   icc_write (s8, 8,-2);
   assert (icc_read (s8, 8) == -2);
   icc_write (s8, 8, 3);     // ICC verison
@@ -352,113 +387,101 @@ const char *babl_space_rgb_to_icc (const Babl *babl, int *ret_length)
 
   icc_write (sign, 36, "acsp"); // changes
 
-
   {
-    int headpos = 0;
-    int tags;
-    int o, no;
-    int p = 0;
-    int psize = 0;
-
-    tags = 10;
-    no = o = 128 + 4 + 12 * tags;
-
-    icc_write (u32,  128, tags);
-#define icc_allocate_tag(tag, size) \
-    no+=((4-o)%4);o = no;psize = size;\
-    icc_write (sign, 128 + 4 + 4 * headpos++, tag);\
-    icc_write (u32,  128 + 4 + 4 * headpos++, o);\
-    icc_write (u32,  128 + 4 + 4 * headpos++, size);\
-    p = no;\
-    no+=size;
-#define icc_duplicate_tag(tag) \
-    icc_write (sign, 128 + 4 + 4 * headpos++, tag);\
-    icc_write (u32,  128 + 4 + 4 * headpos++, p); \
-    icc_write (u32,  128 + 4 + 4 * headpos++, psize);
-
-    icc_allocate_tag ("wtpt", 20);
-    icc_write (sign,o, "XYZ ");
-    icc_write (u32, o + 4, 0);
-    icc_write (s15f16, o + 8, space->whitepoint[0]);
-    icc_write (s15f16, o + 12, space->whitepoint[1]);
-    icc_write (s15f16, o + 16, space->whitepoint[2]);
-
-    icc_allocate_tag ("rXYZ", 20);
-    icc_write (sign,o, "XYZ ");
-    icc_write (u32, o + 4, 0);
-    icc_write (s15f16, o + 8,  space->RGBtoXYZ[0]);
-    icc_write (s15f16, o + 12, space->RGBtoXYZ[3]);
-    icc_write (s15f16, o + 16, space->RGBtoXYZ[6]);
-
-    icc_allocate_tag ("gXYZ", 20);
-    icc_write (sign,o, "XYZ ");
-    icc_write (u32, o + 4, 0);
-    icc_write (s15f16, o + 8,  space->RGBtoXYZ[1]);
-    icc_write (s15f16, o + 12, space->RGBtoXYZ[4]);
-    icc_write (s15f16, o + 16, space->RGBtoXYZ[7]);
-
-    icc_allocate_tag ("bXYZ", 20);
-    icc_write (sign,o, "XYZ ");
-    icc_write (u32, o + 4, 0);
-    icc_write (s15f16, o + 8,  space->RGBtoXYZ[2]);
-    icc_write (s15f16, o + 12, space->RGBtoXYZ[5]);
-    icc_write (s15f16, o + 16, space->RGBtoXYZ[8]);
-
-    icc_allocate_tag ("rTRC", 14);
-    icc_write (sign,o, "curv");
-    icc_write (u32, o + 4, 0);
-    icc_write (u32, o + 8, 1);
-    icc_write (u16, o + 12, 334);
+    state->tags = 10; /* note: we could reserve a couple of spots and
+                        still use a very simple allocator and
+                        still be valid - albeit with tiny waste of
+                        space.
+                */
+    state->no = state->o = 128 + 4 + 12 * state->tags;
+
+    icc_write (u32,  128, state->tags);
+
+    icc_allocate_tag (state, "wtpt", 20);
+    icc_write (sign, state->o, "XYZ ");
+    icc_write (u32,  state->o + 4, 0);
+    icc_write (s15f16, state->o + 8, space->whitepoint[0]);
+    icc_write (s15f16, state->o + 12, space->whitepoint[1]);
+    icc_write (s15f16, state->o + 16, space->whitepoint[2]);
+
+    icc_allocate_tag (state, "rXYZ", 20);
+    icc_write (sign, state->o, "XYZ ");
+    icc_write (u32,  state->o + 4, 0);
+    icc_write (s15f16, state->o + 8,  space->RGBtoXYZ[0]);
+    icc_write (s15f16, state->o + 12, space->RGBtoXYZ[3]);
+    icc_write (s15f16, state->o + 16, space->RGBtoXYZ[6]);
+
+    icc_allocate_tag (state, "gXYZ", 20);
+    icc_write (sign, state->o, "XYZ ");
+    icc_write (u32, state->o + 4, 0);
+    icc_write (s15f16, state->o + 8,  space->RGBtoXYZ[1]);
+    icc_write (s15f16, state->o + 12, space->RGBtoXYZ[4]);
+    icc_write (s15f16, state->o + 16, space->RGBtoXYZ[7]);
+
+    icc_allocate_tag (state, "bXYZ", 20);
+    icc_write (sign, state->o, "XYZ ");
+    icc_write (u32, state->o + 4, 0);
+    icc_write (s15f16, state->o + 8,  space->RGBtoXYZ[2]);
+    icc_write (s15f16, state->o + 12, space->RGBtoXYZ[5]);
+    icc_write (s15f16, state->o + 16, space->RGBtoXYZ[8]);
+
+    icc_allocate_tag (state, "rTRC", 14);
+    icc_write (sign, state->o, "curv");
+    icc_write (u32, state->o + 4, 0);
+    icc_write (u32, state->o + 8, 1);
+    icc_write (u16, state->o + 12, 334);
 
     if (space->trc[0] == space->trc[1] &&
         space->trc[0] == space->trc[2])
     {
-      icc_duplicate_tag ("gTRC");
-      icc_duplicate_tag ("bTRC");
+      icc_duplicate_tag (state, "gTRC");
+      icc_duplicate_tag (state, "bTRC");
     }
     else
     {
-      icc_allocate_tag ("gTRC", 14);
-      icc_write (sign,o, "curv");
-      icc_write (u32, o + 4, 0);
-      icc_write (u32, o + 8, 1); /* forcing a linear curve */
-      icc_allocate_tag ("bTRC", 14);
-      icc_write (sign,o, "curv");
-      icc_write (u32, o + 4, 0);
-      icc_write (u32, o + 8, 1); /* forcing a linear curve */
+      icc_allocate_tag (state, "gTRC", 14);
+      icc_write (sign, state->o, "curv");
+      icc_write (u32, state->o + 4, 0);
+      icc_write (u32, state->o + 8, 1); /* forcing a linear curve */
+      icc_allocate_tag (state, "bTRC", 14);
+      icc_write (sign, state->o, "curv");
+      icc_write (u32, state->o + 4, 0);
+      icc_write (u32, state->o + 8, 1); /* forcing a linear curve */
     }
 
     {
       char str[128];
       int i;
       sprintf (str, "babl");
-      icc_allocate_tag("desc", 100 + strlen (str) + 1);
-      icc_write (sign,o,"desc");
-      icc_write (u32, o + 4, 0);
-      icc_write (u32, o + 8, strlen(str));
+      icc_allocate_tag(state, "desc", 100 + strlen (str) + 1);
+      icc_write (sign, state->o,"desc");
+      icc_write (u32, state->o + 4, 0);
+      icc_write (u32, state->o + 8, strlen(str));
       for (i = 0; str[i]; i++)
-        icc_write (u8, o + 12 + i, str[i]);
+        icc_write (u8, state->o + 12 + i, str[i]);
 
-      icc_duplicate_tag ("dmnd");
+      icc_duplicate_tag (state, "dmnd");
     }
 
     {
       char str[128];
       int i;
       sprintf (str, "CC0/public domain");
-      icc_allocate_tag("cprt", 8 + strlen (str) + 1);
-      icc_write (sign,o, "text");
-      icc_write (u32, o + 4, 0);
+      icc_allocate_tag(state, "cprt", 8 + strlen (str) + 1);
+      icc_write (sign, state->o, "text");
+      icc_write (u32, state->o + 4, 0);
       for (i = 0; str[i]; i++)
-        icc_write (u8, o + 8 + i, str[i]);
+        icc_write (u8, state->o + 8 + i, str[i]);
     }
 
-    icc_write (u32, 0, no + 3);
-    length = no + 3;
+    icc_write (u32, 0, state->no + 3);
+    length = state->no + 3;
   }
 
   if (ret_length)
     *ret_length = length;
+
+  babl_free (state);
   return icc;
 }
 
@@ -467,6 +490,8 @@ babl_space_rgb_icc (const char *icc,
                     int         length,
                     char      **error)
 {
+  ICC *state = icc_state_new ((char*)icc, length, 0);
+
   int  profile_size     = icc_read (u32, 0);
   int  icc_ver_major    = icc_read (u8, 8);
   const Babl *trc_red   = NULL;
@@ -477,54 +502,56 @@ babl_space_rgb_icc (const char *icc,
   if (profile_size != length)
   {
     *error = "icc profile length inconsistency";
-    return NULL;
   }
-  if (icc_ver_major > 2)
+  else if (icc_ver_major > 2)
   {
     *error = "only ICC v2 profiles supported";
-    return NULL;
   }
+  else
+  {
   profile_class = icc_read (sign, 12);
   if (strcmp (profile_class.str, "mntr"))
-  {
     *error = "not a monitor-class profile";
-    return NULL;
-  }
+  else
+  {
   color_space = icc_read (sign, 16);
   if (strcmp (color_space.str, "RGB "))
-  {
     *error = "not defining an RGB space";
-    return NULL;
   }
+  }
+
   {
      int offset, element_size;
-     if (icc_tag (icc, length, "rTRC", &offset, &element_size))
+     if (!*error && icc_tag (state, "rTRC", &offset, &element_size))
      {
-       trc_red = babl_trc_from_icc (icc + offset, element_size, error);
-       if (*error) return NULL;
+       trc_red = babl_trc_from_icc (state, offset, error);
      }
-     if (icc_tag (icc, length, "gTRC", &offset, &element_size))
+     if (!*error && icc_tag (state, "gTRC", &offset, &element_size))
      {
-       trc_green = babl_trc_from_icc (icc + offset, element_size, error);
-       if (*error) return NULL;
+       trc_green = babl_trc_from_icc (state, offset, error);
      }
-     if (icc_tag (icc, length, "bTRC", &offset, &element_size))
+     if (!*error && icc_tag (state, "bTRC", &offset, &element_size))
      {
-       trc_blue = babl_trc_from_icc (icc + offset, element_size, error);
-       if (*error) return NULL;
+       trc_blue = babl_trc_from_icc (state, offset, error);
      }
   }
 
-  if (!trc_red || !trc_green || !trc_blue)
+
+  if (!*error && (!trc_red || !trc_green || !trc_blue))
   {
      *error = "missing TRCs";
-     return NULL;
   }
 
-  if (icc_tag (icc, length, "rXYZ", NULL, NULL) &&
-           icc_tag (icc, length, "gXYZ", NULL, NULL) &&
-           icc_tag (icc, length, "bXYZ", NULL, NULL) &&
-           icc_tag (icc, length, "wtpt", NULL, NULL))
+  if (*error)
+  {
+    babl_free (state);
+    return NULL;
+  }
+
+  if (icc_tag (state, "rXYZ", NULL, NULL) &&
+           icc_tag (state, "gXYZ", NULL, NULL) &&
+           icc_tag (state, "bXYZ", NULL, NULL) &&
+           icc_tag (state, "wtpt", NULL, NULL))
   {
      int offset, element_size;
      double rx, gx, bx;
@@ -533,22 +560,24 @@ babl_space_rgb_icc (const char *icc,
 
      double wX, wY, wZ;
 
-     icc_tag (icc, length, "rXYZ", &offset, &element_size);
+     icc_tag (state, "rXYZ", &offset, &element_size);
      rx = icc_read (s15f16, offset + 8 + 4 * 0);
      ry = icc_read (s15f16, offset + 8 + 4 * 1);
      rz = icc_read (s15f16, offset + 8 + 4 * 2);
-     icc_tag (icc, length, "gXYZ", &offset, &element_size);
+     icc_tag (state, "gXYZ", &offset, &element_size);
      gx = icc_read (s15f16, offset + 8 + 4 * 0);
      gy = icc_read (s15f16, offset + 8 + 4 * 1);
      gz = icc_read (s15f16, offset + 8 + 4 * 2);
-     icc_tag (icc, length, "bXYZ", &offset, &element_size);
+     icc_tag (state, "bXYZ", &offset, &element_size);
      bx = icc_read (s15f16, offset + 8 + 4 * 0);
      by = icc_read (s15f16, offset + 8 + 4 * 1);
      bz = icc_read (s15f16, offset + 8 + 4 * 2);
-     icc_tag (icc, length, "wtpt", &offset, &element_size);
+     icc_tag (state, "wtpt", &offset, &element_size);
      wX = icc_read (s15f16, offset + 8);
      wY = icc_read (s15f16, offset + 8 + 4);
      wZ = icc_read (s15f16, offset + 8 + 4 * 2);
+    
+     babl_free (state);
 
      return babl_space_rgb_matrix (NULL,
                 wX, wY, wZ,
@@ -557,14 +586,14 @@ babl_space_rgb_icc (const char *icc,
                 rz, gz, bz,
                 trc_red, trc_green, trc_blue);
   }
-  else if (icc_tag (icc, length, "chrm", NULL, NULL) &&
-           icc_tag (icc, length, "wtpt", NULL, NULL))
+  else if (icc_tag (state, "chrm", NULL, NULL) &&
+           icc_tag (state, "wtpt", NULL, NULL))
   {
      int offset, element_size;
      double red_x, red_y, green_x, green_y, blue_x, blue_y;
      int channels, phosporant;
 
-     icc_tag (icc, length, "chrm", &offset, &element_size);
+     icc_tag (state, "chrm", &offset, &element_size);
      channels   = icc_read (u16, offset + 8);
      phosporant = icc_read (u16, offset + 10);
 
@@ -586,11 +615,12 @@ babl_space_rgb_icc (const char *icc,
      blue_x  = icc_read (s15f16, offset + 28);
      blue_y  = icc_read (s15f16, offset + 28 + 4);
 
-     icc_tag (icc, length, "wtpt", &offset, &element_size);
+     icc_tag (state, "wtpt", &offset, &element_size);
      {
        double wX = icc_read (s15f16, offset + 8);
        double wY = icc_read (s15f16, offset + 8 + 4);
        double wZ = icc_read (s15f16, offset + 8 + 4 * 2);
+       babl_free (state);
 
        return babl_space_rgb_chromaticities (NULL,
                        wX / (wX + wY + wZ),
@@ -604,5 +634,6 @@ babl_space_rgb_icc (const char *icc,
   }
 
   *error = "didnt find RGB primaries";
+  babl_free (state);
   return NULL;
 }
diff --git a/babl/babl-internal.h b/babl/babl-internal.h
index b9c287e..4232710 100644
--- a/babl/babl-internal.h
+++ b/babl/babl-internal.h
@@ -355,9 +355,12 @@ void babl_space_get_chromaticities  (const Babl *space,
                                      double *gx, double *gy,
                                      double *bx, double *by);
 
-const Babl * babl_trc_new (const char *name,
-                           BablTRCType type,
-                           double      gamma);
+const Babl *
+babl_trc_new (const char *name,
+              BablTRCType type,
+              double      gamma,
+              int         n_lut,
+              float      *lut);
 
 /**
  * babl_trc_from_linear:
diff --git a/babl/babl-trc.c b/babl/babl-trc.c
index 9f8cb58..5719e03 100644
--- a/babl/babl-trc.c
+++ b/babl/babl-trc.c
@@ -40,7 +40,9 @@ babl_trc (const char *name)
 const Babl *
 babl_trc_new (const char *name,
               BablTRCType type,
-              double      gamma)
+              double      gamma,
+              int         n_lut,
+              float      *lut)
 {
   int i=0;
   static BablTRC trc;
@@ -74,6 +76,11 @@ babl_trc_new (const char *name,
   return (Babl*)&trc_db[i];
 }
 
+const Babl * babl_trc_lut   (const char *name, int n, float *entries)
+{
+  return babl_trc_new (name, BABL_TRC_LUT, 0, n, entries);
+}
+
 void
 babl_trc_class_for_each (BablEachFunction each_fun,
                            void            *user_data)
@@ -90,24 +97,24 @@ babl_trc_gamma (double gamma)
   char name[32];
   int i;
   if (fabs (gamma - 1.0) < 0.0001)
-     return babl_trc_new ("linear", BABL_TRC_LINEAR, 1.0);
+     return babl_trc_new ("linear", BABL_TRC_LINEAR, 1.0, 0, NULL);
   sprintf (name, "%.6f", gamma);
   for (i = 0; name[i]; i++)
     if (name[i] == ',') name[i] = '.';
   while (name[strlen(name)-1]=='0')
     name[strlen(name)-1]='\0';
-  return babl_trc_new (name,   BABL_TRC_GAMMA, gamma);
+  return babl_trc_new (name,   BABL_TRC_GAMMA, gamma, 0, NULL);
 }
 
+
 void
 babl_trc_class_init (void)
 {
-  /* we register sRGB first so that lookups for it is fastest */
-  babl_trc_new ("sRGB",  BABL_TRC_SRGB,    2.2);
+  babl_trc_new ("sRGB",  BABL_TRC_SRGB, 2.2, 0, NULL);
   babl_trc_gamma (2.2);
   babl_trc_gamma (1.8);
   babl_trc_gamma (1.0);
-  babl_trc_new ("linear", BABL_TRC_LINEAR, 1.0);
+  babl_trc_new ("linear", BABL_TRC_LINEAR, 1.0, 0, NULL);
 }
 
 double babl_trc_from_linear (const Babl *trc_, double value)
diff --git a/babl/babl-trc.h b/babl/babl-trc.h
index fd7a0c5..c762810 100644
--- a/babl/babl-trc.h
+++ b/babl/babl-trc.h
@@ -27,7 +27,8 @@ BABL_CLASS_DECLARE (trc);
 
 typedef enum {BABL_TRC_LINEAR,
               BABL_TRC_GAMMA,
-              BABL_TRC_SRGB} BablTRCType;
+              BABL_TRC_SRGB,
+              BABL_TRC_LUT} BablTRCType;
 
 typedef struct
 {
@@ -35,9 +36,20 @@ typedef struct
   BablTRCType      type;
   double           gamma;
   char             name[128];
-
+  float           *lut;
+  int              lut_size;
 } BablTRC;
 
+static inline double babl_trc_lut_from_linear (const Babl *trc_, double value)
+{
+  return 0;
+}
+
+static inline double babl_trc_lut_to_linear (const Babl *trc_, double value)
+{
+  return 0;
+}
+
 static inline double _babl_trc_from_linear (const Babl *trc_, double value)
 {
   BablTRC *trc = (void*)trc_;
@@ -49,6 +61,8 @@ static inline double _babl_trc_from_linear (const Babl *trc_, double value)
             return pow (value, 1.0/trc->gamma);
     case BABL_TRC_SRGB:
             return babl_linear_to_gamma_2_2 (value);
+    case BABL_TRC_LUT:
+            return babl_trc_lut_from_linear (trc_, value);
   }
   return value;
 }
@@ -64,6 +78,8 @@ static inline double _babl_trc_to_linear (const Babl *trc_, double value)
             return pow (value, trc->gamma);
     case BABL_TRC_SRGB:
             return babl_gamma_2_2_to_linear (value);
+    case BABL_TRC_LUT:
+            return babl_trc_lut_to_linear (trc_, value);
   }
   return value;
 }
@@ -76,6 +92,7 @@ static inline float _babl_trc_from_linearf (const Babl *trc_, float value)
     case BABL_TRC_LINEAR: return value;
     case BABL_TRC_GAMMA:  return powf (value, 1.0f/trc->gamma);
     case BABL_TRC_SRGB:   return babl_linear_to_gamma_2_2f (value);
+    case BABL_TRC_LUT:    return babl_trc_lut_from_linear (trc_, value);
   }
   return value;
 }
@@ -88,6 +105,7 @@ static inline float _babl_trc_to_linearf (const Babl *trc_, float value)
     case BABL_TRC_LINEAR: return value;
     case BABL_TRC_GAMMA:  return powf (value, trc->gamma);
     case BABL_TRC_SRGB:   return babl_gamma_2_2_to_linearf (value);
+    case BABL_TRC_LUT:    return babl_trc_lut_to_linear (trc_, value);
   }
   return value;
 }
diff --git a/babl/babl.h b/babl/babl.h
index b601615..e05ea49 100644
--- a/babl/babl.h
+++ b/babl/babl.h
@@ -91,10 +91,13 @@ const Babl * babl_trc       (const char *name);
 /**
  * babl_trc_gamma:
  *
- * Creates a Babl TRC for a specific gamma value.
+ * Creates a Babl TRC for a specific gamma value, it will be given
+ * a name 
  */
 const Babl * babl_trc_gamma (double gamma);
 
+const Babl * babl_trc_lut   (const char *name, int n, float *entries);
+
 
 /**
  * babl_space:


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