< prev index next >

src/java.desktop/share/native/liblcms/cmscgats.c

Print this page
*** 85,19 ***
          SCOMMENT,   // comment
          SEOLN,      // End of line
          SEOF,       // End of stream
          SSYNERROR,  // Syntax error found on stream
  
!         // Keywords
  
          SBEGIN_DATA,
          SBEGIN_DATA_FORMAT,
          SEND_DATA,
          SEND_DATA_FORMAT,
          SKEYWORD,
          SDATA_FORMAT_ID,
!         SINCLUDE
  
      } SYMBOL;
  
  
  // How to write the value
--- 85,31 ---
          SCOMMENT,   // comment
          SEOLN,      // End of line
          SEOF,       // End of stream
          SSYNERROR,  // Syntax error found on stream
  
!         // IT8 symbols
  
          SBEGIN_DATA,
          SBEGIN_DATA_FORMAT,
          SEND_DATA,
          SEND_DATA_FORMAT,
          SKEYWORD,
          SDATA_FORMAT_ID,
!         SINCLUDE,
+ 
+         // Cube symbols
+ 
+         SDOMAIN_MAX,
+         SDOMAIN_MIN,
+         S_LUT1D_SIZE,
+         S_LUT1D_INPUT_RANGE,
+         S_LUT3D_SIZE,
+         S_LUT3D_INPUT_RANGE,
+         S_LUT_IN_VIDEO_RANGE,
+         S_LUT_OUT_VIDEO_RANGE,
+         STITLE
  
      } SYMBOL;
  
  
  // How to write the value

*** 176,10 ***
--- 188,14 ---
  typedef struct struct_it8 {
  
          cmsUInt32Number  TablesCount;                     // How many tables in this stream
          cmsUInt32Number  nTable;                          // The actual table
  
+         // Partser type
+         cmsBool        IsCUBE;
+ 
+         // Tables
          TABLE Tab[MAXTABLES];
  
          // Memory management
          OWNEDMEM*      MemorySink;            // The storage backend
          SUBALLOCATOR   Allocator;             // String suballocator -- just to keep it fast

*** 235,12 ***
          const char *id;
          SYMBOL sy;
  
     } KEYWORD;
  
! // The keyword->symbol translation table. Sorting is required.
! static const KEYWORD TabKeys[] = {
  
          {"$INCLUDE",               SINCLUDE},   // This is an extension!
          {".INCLUDE",               SINCLUDE},   // This is an extension!
  
          {"BEGIN_DATA",             SBEGIN_DATA },
--- 251,12 ---
          const char *id;
          SYMBOL sy;
  
     } KEYWORD;
  
! // The keyword->symbol translation tables. Sorting is required.
! static const KEYWORD TabKeysIT8[] = {
  
          {"$INCLUDE",               SINCLUDE},   // This is an extension!
          {".INCLUDE",               SINCLUDE},   // This is an extension!
  
          {"BEGIN_DATA",             SBEGIN_DATA },

*** 249,11 ***
          {"END_DATA",               SEND_DATA},
          {"END_DATA_FORMAT",        SEND_DATA_FORMAT},
          {"KEYWORD",                SKEYWORD}
          };
  
! #define NUMKEYS (sizeof(TabKeys)/sizeof(KEYWORD))
  
  // Predefined properties
  
  // A property
  typedef struct {
--- 265,29 ---
          {"END_DATA",               SEND_DATA},
          {"END_DATA_FORMAT",        SEND_DATA_FORMAT},
          {"KEYWORD",                SKEYWORD}
          };
  
! #define NUMKEYS_IT8 (sizeof(TabKeysIT8)/sizeof(KEYWORD))
+ 
+ static const KEYWORD TabKeysCUBE[] = {
+ 
+         {"DOMAIN_MAX",             SDOMAIN_MAX },
+         {"DOMAIN_MIN",             SDOMAIN_MIN },
+         {"LUT_1D_SIZE",            S_LUT1D_SIZE },
+         {"LUT_1D_INPUT_RANGE",     S_LUT1D_INPUT_RANGE },
+         {"LUT_3D_SIZE",            S_LUT3D_SIZE },
+         {"LUT_3D_INPUT_RANGE",     S_LUT3D_INPUT_RANGE },
+         {"LUT_IN_VIDEO_RANGE",     S_LUT_IN_VIDEO_RANGE },
+         {"LUT_OUT_VIDEO_RANGE",    S_LUT_OUT_VIDEO_RANGE },
+         {"TITLE",                  STITLE }
+ 
+ };
+ 
+ #define NUMKEYS_CUBE (sizeof(TabKeysCUBE)/sizeof(KEYWORD))
+ 
+ 
  
  // Predefined properties
  
  // A property
  typedef struct {

*** 453,11 ***
  
  // Checks whatever c is a separator
  static
  cmsBool isseparator(int c)
  {
!     return (c == ' ') || (c == '\t') ;
  }
  
  // Checks whatever c is a valid identifier char
  static
  cmsBool ismiddle(int c)
--- 487,11 ---
  
  // Checks whatever c is a separator
  static
  cmsBool isseparator(int c)
  {
!     return (c == ' ') || (c == '\t');
  }
  
  // Checks whatever c is a valid identifier char
  static
  cmsBool ismiddle(int c)

*** 474,11 ***
  
  // Checks whatsever c is a valid identifier first char.
  static
  cmsBool isfirstidchar(int c)
  {
!      return !isdigit(c) && ismiddle(c);
  }
  
  // Guess whether the supplied path looks like an absolute path
  static
  cmsBool isabsolutepath(const char *path)
--- 508,11 ---
  
  // Checks whatsever c is a valid identifier first char.
  static
  cmsBool isfirstidchar(int c)
  {
!      return c != '-' && !isdigit(c) && ismiddle(c);
  }
  
  // Guess whether the supplied path looks like an absolute path
  static
  cmsBool isabsolutepath(const char *path)

*** 513,17 ***
      cmsUInt32Number len;
  
      // Already absolute?
      if (isabsolutepath(relPath)) {
  
!         strncpy(buffer, relPath, MaxLen);
          buffer[MaxLen-1] = 0;
          return TRUE;
      }
  
      // No, search for last
!     strncpy(buffer, basePath, MaxLen);
      buffer[MaxLen-1] = 0;
  
      tail = strrchr(buffer, DIR_CHAR);
      if (tail == NULL) return FALSE;    // Is not absolute and has no separators??
  
--- 547,17 ---
      cmsUInt32Number len;
  
      // Already absolute?
      if (isabsolutepath(relPath)) {
  
!         memcpy(buffer, relPath, MaxLen);
          buffer[MaxLen-1] = 0;
          return TRUE;
      }
  
      // No, search for last
!     memcpy(buffer, basePath, MaxLen);
      buffer[MaxLen-1] = 0;
  
      tail = strrchr(buffer, DIR_CHAR);
      if (tail == NULL) return FALSE;    // Is not absolute and has no separators??
  

*** 601,14 ***
  }
  
  
  // Try to see if current identifier is a keyword, if so return the referred symbol
  static
! SYMBOL BinSrchKey(const char *id)
  {
      int l = 1;
!     int r = NUMKEYS;
      int x, res;
  
      while (r >= l)
      {
          x = (l+r)/2;
--- 635,14 ---
  }
  
  
  // Try to see if current identifier is a keyword, if so return the referred symbol
  static
! SYMBOL BinSrchKey(const char *id, int NumKeys, const KEYWORD* TabKeys)
  {
      int l = 1;
!     int r = NumKeys;
      int x, res;
  
      while (r >= l)
      {
          x = (l+r)/2;

*** 774,11 ***
  
      return sign * dnum;
  }
  
  
! // Reads a string, special case to avoid infinite resursion on .include
  static
  void InStringSymbol(cmsIT8* it8)
  {
      while (isseparator(it8->ch))
          NextCh(it8);
--- 808,11 ---
  
      return sign * dnum;
  }
  
  
! // Reads a string, special case to avoid infinite recursion on .include
  static
  void InStringSymbol(cmsIT8* it8)
  {
      while (isseparator(it8->ch))
          NextCh(it8);

*** 831,11 ***
                  NextCh(it8);
  
              } while (isidchar(it8->ch));
  
  
!             key = BinSrchKey(StringPtr(it8->id));
              if (key == SUNDEFINED) it8->sy = SIDENT;
              else it8->sy = key;
  
          }
          else                         // Is a number?
--- 865,13 ---
                  NextCh(it8);
  
              } while (isidchar(it8->ch));
  
  
!             key = BinSrchKey(StringPtr(it8->id),
+                     it8->IsCUBE ? NUMKEYS_CUBE : NUMKEYS_IT8,
+                     it8->IsCUBE ? TabKeysCUBE : TabKeysIT8);
              if (key == SUNDEFINED) it8->sy = SIDENT;
              else it8->sy = key;
  
          }
          else                         // Is a number?

*** 940,10 ***
--- 976,11 ---
                      else {
  
                          snprintf(buffer, sizeof(buffer), it8 ->DoubleFormatter, it8->dnum);
                      }
  
+                     StringClear(it8->id);
                      StringCat(it8->id, buffer);
  
                      do {
  
                          StringAppend(it8->id, (char) it8->ch);

*** 969,11 ***
  
  
          // Next line
          case '\r':
              NextCh(it8);
!             if (it8 ->ch == '\n')
                  NextCh(it8);
              it8->sy = SEOLN;
              it8->lineno++;
              break;
  
--- 1006,11 ---
  
  
          // Next line
          case '\r':
              NextCh(it8);
!             if (it8->ch == '\n')
                  NextCh(it8);
              it8->sy = SEOLN;
              it8->lineno++;
              break;
  

*** 1290,11 ***
  
      if (IsAvailableOnList(*Head, Key, Subkey, &p)) {
  
          // This may work for editing properties
  
!         //     return SynError(it8, "duplicate key <%s>", Key);
      }
      else {
  
          last = p;
  
--- 1327,16 ---
  
      if (IsAvailableOnList(*Head, Key, Subkey, &p)) {
  
          // This may work for editing properties
  
!         if (cmsstrcasecmp(Key, "NUMBER_OF_FIELDS") == 0 ||
+             cmsstrcasecmp(Key, "NUMBER_OF_SETS") == 0) {
+ 
+             SynError(it8, "duplicate key <%s>", Key);
+             return NULL;
+         }
      }
      else {
  
          last = p;
  

*** 1411,10 ***
--- 1453,12 ---
      AllocTable(it8);
  
      it8->MemoryBlock = NULL;
      it8->MemorySink  = NULL;
  
+     it8->IsCUBE = FALSE;
+ 
      it8 ->nTable = 0;
  
      it8->ContextID = ContextID;
      it8->Allocator.Used = 0;
      it8->Allocator.Block = NULL;

*** 1692,11 ***
  {
      TABLE* t = GetTable(it8);
      int nSamples    = t -> nSamples;
      int nPatches    = t -> nPatches;
  
!     if (nSet >= nPatches || nField >= nSamples)
          return NULL;
  
      if (!t->Data) return NULL;
      return t->Data [nSet * nSamples + nField];
  }
--- 1736,11 ---
  {
      TABLE* t = GetTable(it8);
      int nSamples    = t -> nSamples;
      int nPatches    = t -> nPatches;
  
!     if (nSet < 0 || nSet >= nPatches || nField < 0 || nField >= nSamples)
          return NULL;
  
      if (!t->Data) return NULL;
      return t->Data [nSet * nSamples + nField];
  }

*** 1877,57 ***
  
         WriteStr(fp, "BEGIN_DATA_FORMAT\n");
         WriteStr(fp, " ");
         nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
  
!        for (i = 0; i < nSamples; i++) {
  
!               WriteStr(fp, t->DataFormat[i]);
!               WriteStr(fp, ((i == (nSamples-1)) ? "\n" : "\t"));
!           }
  
         WriteStr (fp, "END_DATA_FORMAT\n");
  }
  
  
  // Writes data array
  static
  void WriteData(SAVESTREAM* fp, cmsIT8* it8)
  {
!        int  i, j;
         TABLE* t = GetTable(it8);
  
         if (!t->Data) return;
  
         WriteStr (fp, "BEGIN_DATA\n");
  
!        t->nPatches = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
  
!        for (i = 0; i < t-> nPatches; i++) {
  
!               WriteStr(fp, " ");
  
!               for (j = 0; j < t->nSamples; j++) {
  
!                      char *ptr = t->Data[i*t->nSamples+j];
  
!                      if (ptr == NULL) WriteStr(fp, "\"\"");
-                      else {
-                          // If value contains whitespace, enclose within quote
  
!                          if (strchr(ptr, ' ') != NULL) {
  
!                              WriteStr(fp, "\"");
-                              WriteStr(fp, ptr);
-                              WriteStr(fp, "\"");
-                          }
-                          else
-                             WriteStr(fp, ptr);
-                      }
  
!                      WriteStr(fp, ((j == (t->nSamples-1)) ? "\n" : "\t"));
!               }
         }
         WriteStr (fp, "END_DATA\n");
  }
  
  
--- 1921,63 ---
  
         WriteStr(fp, "BEGIN_DATA_FORMAT\n");
         WriteStr(fp, " ");
         nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
  
!        if (nSamples <= t->nSamples) {
  
!            for (i = 0; i < nSamples; i++) {
! 
!                WriteStr(fp, t->DataFormat[i]);
+                WriteStr(fp, ((i == (nSamples - 1)) ? "\n" : "\t"));
+            }
+        }
  
         WriteStr (fp, "END_DATA_FORMAT\n");
  }
  
  
  // Writes data array
  static
  void WriteData(SAVESTREAM* fp, cmsIT8* it8)
  {
!        int  i, j, nPatches;
         TABLE* t = GetTable(it8);
  
         if (!t->Data) return;
  
         WriteStr (fp, "BEGIN_DATA\n");
  
!        nPatches = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
  
!        if (nPatches <= t->nPatches) {
  
!            for (i = 0; i < nPatches; i++) {
  
!                WriteStr(fp, " ");
  
!                for (j = 0; j < t->nSamples; j++) {
  
!                    char* ptr = t->Data[i * t->nSamples + j];
  
!                    if (ptr == NULL) WriteStr(fp, "\"\"");
+                    else {
+                        // If value contains whitespace, enclose within quote
  
!                        if (strchr(ptr, ' ') != NULL) {
  
!                            WriteStr(fp, "\"");
!                            WriteStr(fp, ptr);
+                            WriteStr(fp, "\"");
+                        }
+                        else
+                            WriteStr(fp, ptr);
+                    }
+ 
+                    WriteStr(fp, ((j == (t->nSamples - 1)) ? "\n" : "\t"));
+                }
+            }
         }
         WriteStr (fp, "END_DATA\n");
  }
  
  

*** 1944,19 ***
      sd.stream = fopen(cFileName, "wt");
      if (!sd.stream) return FALSE;
  
      for (i=0; i < it8 ->TablesCount; i++) {
  
!             cmsIT8SetTable(hIT8, i);
!             WriteHeader(it8, &sd);
!             WriteDataFormat(&sd, it8);
!             WriteData(&sd, it8);
      }
  
      if (fclose(sd.stream) != 0) return FALSE;
- 
      return TRUE;
  }
  
  
  // Saves to memory
  cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* BytesNeeded)
--- 1994,33 ---
      sd.stream = fopen(cFileName, "wt");
      if (!sd.stream) return FALSE;
  
      for (i=0; i < it8 ->TablesCount; i++) {
  
!         TABLE* t;
! 
!         if (cmsIT8SetTable(hIT8, i) < 0) goto Error;
! 
+         /**
+         * Check for wrong data
+         */
+         t = GetTable(it8);
+         if (t->Data == NULL) goto Error;
+         if (t->DataFormat == NULL) goto Error;
+ 
+         WriteHeader(it8, &sd);
+         WriteDataFormat(&sd, it8);
+         WriteData(&sd, it8);
      }
  
      if (fclose(sd.stream) != 0) return FALSE;
      return TRUE;
+ 
+ Error:
+     fclose(sd.stream);
+     return FALSE;
+ 
  }
  
  
  // Saves to memory
  cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* BytesNeeded)

*** 2329,82 ***
  void CookPointers(cmsIT8* it8)
  {
      int idField, i;
      char* Fld;
      cmsUInt32Number j;
!     cmsUInt32Number nOldTable = it8 ->nTable;
  
!     for (j=0; j < it8 ->TablesCount; j++) {
  
!     TABLE* t = it8 ->Tab + j;
  
!     t -> SampleID = 0;
!     it8 ->nTable = j;
  
!     for (idField = 0; idField < t -> nSamples; idField++)
!     {
!         if (t ->DataFormat == NULL){
!             SynError(it8, "Undefined DATA_FORMAT");
!             return;
!         }
  
!         Fld = t->DataFormat[idField];
!         if (!Fld) continue;
  
  
!         if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) {
  
!             t -> SampleID = idField;
!         }
  
!         // "LABEL" is an extension. It keeps references to forward tables
  
!         if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$') {
  
!             // Search for table references...
!             for (i = 0; i < t->nPatches; i++) {
  
!                 char* Label = GetData(it8, i, idField);
  
!                 if (Label) {
  
!                     cmsUInt32Number k;
  
!                     // This is the label, search for a table containing
!                     // this property
  
!                     for (k = 0; k < it8->TablesCount; k++) {
  
!                         TABLE* Table = it8->Tab + k;
!                         KEYVALUE* p;
  
!                         if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) {
  
!                             // Available, keep type and table
!                             char Buffer[256];
  
!                             char* Type = p->Value;
!                             int  nTable = (int)k;
  
!                             snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type);
  
!                             SetData(it8, i, idField, Buffer);
                          }
                      }
- 
- 
                  }
- 
              }
- 
- 
          }
- 
-     }
      }
  
!     it8 ->nTable = nOldTable;
  }
  
  // Try to infere if the file is a CGATS/IT8 file at all. Read first line
  // that should be something like some printable characters plus a \n
  // returns 0 if this is not like a CGATS, or an integer otherwise. This integer is the number of words in first line?
--- 2393,76 ---
  void CookPointers(cmsIT8* it8)
  {
      int idField, i;
      char* Fld;
      cmsUInt32Number j;
!     cmsUInt32Number nOldTable = it8->nTable;
  
!     for (j = 0; j < it8->TablesCount; j++) {
  
!         TABLE* t = it8->Tab + j;
  
!         t->SampleID = 0;
!         it8->nTable = j;
  
!         for (idField = 0; idField < t->nSamples; idField++)
!         {
!             if (t->DataFormat == NULL) {
!                 SynError(it8, "Undefined DATA_FORMAT");
!                 return;
!             }
  
!             Fld = t->DataFormat[idField];
!             if (!Fld) continue;
  
  
!             if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) {
  
!                 t->SampleID = idField;
!             }
  
!             // "LABEL" is an extension. It keeps references to forward tables
  
!             if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$') {
  
!                 // Search for table references...
!                 for (i = 0; i < t->nPatches; i++) {
  
!                     char* Label = GetData(it8, i, idField);
  
!                     if (Label) {
  
!                         cmsUInt32Number k;
  
!                         // This is the label, search for a table containing
!                         // this property
  
!                         for (k = 0; k < it8->TablesCount; k++) {
  
!                             TABLE* Table = it8->Tab + k;
!                             KEYVALUE* p;
  
!                             if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) {
  
!                                 // Available, keep type and table
!                                 char Buffer[256];
  
!                                 char* Type = p->Value;
!                                 int  nTable = (int)k;
  
!                                 snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type);
  
!                                 SetData(it8, i, idField, Buffer);
+                             }
                          }
                      }
                  }
              }
          }
      }
  
!     it8->nTable = nOldTable;
  }
  
  // Try to infere if the file is a CGATS/IT8 file at all. Read first line
  // that should be something like some printable characters plus a \n
  // returns 0 if this is not like a CGATS, or an integer otherwise. This integer is the number of words in first line?

*** 2491,11 ***
      it8 = (cmsIT8*) hIT8;
      it8 ->MemoryBlock = (char*) _cmsMalloc(ContextID, len + 1);
      if (it8->MemoryBlock == NULL)
      {
          cmsIT8Free(hIT8);
!         return FALSE;
      }
  
      strncpy(it8 ->MemoryBlock, (const char*) Ptr, len);
      it8 ->MemoryBlock[len] = 0;
  
--- 2549,11 ---
      it8 = (cmsIT8*) hIT8;
      it8 ->MemoryBlock = (char*) _cmsMalloc(ContextID, len + 1);
      if (it8->MemoryBlock == NULL)
      {
          cmsIT8Free(hIT8);
!         return NULL;
      }
  
      strncpy(it8 ->MemoryBlock, (const char*) Ptr, len);
      it8 ->MemoryBlock[len] = 0;
  

*** 2503,11 ***
      it8-> Source = it8 -> MemoryBlock;
  
      if (!ParseIT8(it8, type-1)) {
  
          cmsIT8Free(hIT8);
!         return FALSE;
      }
  
      CookPointers(it8);
      it8 ->nTable = 0;
  
--- 2561,11 ---
      it8-> Source = it8 -> MemoryBlock;
  
      if (!ParseIT8(it8, type-1)) {
  
          cmsIT8Free(hIT8);
!         return NULL;
      }
  
      CookPointers(it8);
      it8 ->nTable = 0;
  

*** 2600,21 ***
      for (p = t -> HeaderList;  p != NULL; p = p->Next) {
          n++;
      }
  
  
!         Props = (char**)AllocChunk(it8, sizeof(char*) * n);
!         if (Props != NULL) {
- 
-                 // Pass#2 - Fill pointers
-                 n = 0;
-                 for (p = t->HeaderList; p != NULL; p = p->Next) {
-                         Props[n++] = p->Keyword;
-                 }
  
          }
!         *PropertyNames = Props;
  
      return n;
  }
  
  cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cProp, const char ***SubpropertyNames)
--- 2658,21 ---
      for (p = t -> HeaderList;  p != NULL; p = p->Next) {
          n++;
      }
  
  
!     Props = (char**)AllocChunk(it8, sizeof(char*) * n);
!     if (Props != NULL) {
  
+         // Pass#2 - Fill pointers
+         n = 0;
+         for (p = t->HeaderList; p != NULL; p = p->Next) {
+             Props[n++] = p->Keyword;
          }
! 
+     }
+     *PropertyNames = Props;
  
      return n;
  }
  
  cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cProp, const char ***SubpropertyNames)

*** 2970,5 ***
--- 3028,238 ---
          strncpy(it8->DoubleFormatter, Formatter, sizeof(it8->DoubleFormatter));
  
      it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0;
  }
  
+ 
+ static
+ cmsBool ReadNumbers(cmsIT8* cube, int n, cmsFloat64Number* arr)
+ {
+     int i;
+ 
+     for (i = 0; i < n; i++) {
+ 
+         if (cube->sy == SINUM)
+             arr[i] = cube->inum;
+         else
+             if (cube->sy == SDNUM)
+                 arr[i] = cube->dnum;
+             else
+                 return SynError(cube, "Number expected");
+ 
+         InSymbol(cube);
+     }
+ 
+     return CheckEOLN(cube);
+ }
+ 
+ static
+ cmsBool ParseCube(cmsIT8* cube, cmsStage** Shaper, cmsStage** CLUT, char title[])
+ {
+     cmsFloat64Number domain_min[3] = { 0, 0, 0 };
+     cmsFloat64Number domain_max[3] = { 1.0, 1.0, 1.0 };
+     cmsFloat64Number check_0_1[2] = { 0, 1.0 };
+     int shaper_size = 0;
+     int lut_size = 0;
+     int i;
+ 
+     InSymbol(cube);
+ 
+     while (cube->sy != SEOF) {
+         switch (cube->sy)
+         {
+         // Set profile description
+         case STITLE:
+             InSymbol(cube);
+             if (!Check(cube, SSTRING, "Title string expected")) return FALSE;
+             memcpy(title, StringPtr(cube->str), MAXSTR);
+             title[MAXSTR - 1] = 0;
+             InSymbol(cube);
+             break;
+ 
+         // Define domain
+         case SDOMAIN_MIN:
+             InSymbol(cube);
+             if (!ReadNumbers(cube, 3, domain_min)) return FALSE;
+             break;
+ 
+         case SDOMAIN_MAX:
+             InSymbol(cube);
+             if (!ReadNumbers(cube, 3, domain_max)) return FALSE;
+             break;
+ 
+         // Define shaper
+         case S_LUT1D_SIZE:
+             InSymbol(cube);
+             if (!Check(cube, SINUM, "Shaper size expected")) return FALSE;
+             shaper_size = cube->inum;
+             InSymbol(cube);
+             break;
+ 
+         // Deefine CLUT
+         case S_LUT3D_SIZE:
+             InSymbol(cube);
+             if (!Check(cube, SINUM, "LUT size expected")) return FALSE;
+             lut_size = cube->inum;
+             InSymbol(cube);
+             break;
+ 
+         // Range. If present, has to be 0..1.0
+         case S_LUT1D_INPUT_RANGE:
+         case S_LUT3D_INPUT_RANGE:
+             InSymbol(cube);
+             if (!ReadNumbers(cube, 2, check_0_1)) return FALSE;
+             if (check_0_1[0] != 0 || check_0_1[1] != 1.0) {
+                 return SynError(cube, "Unsupported format");
+             }
+             break;
+ 
+         case SEOLN:
+             InSymbol(cube);
+             break;
+ 
+         default:
+         case S_LUT_IN_VIDEO_RANGE:
+         case S_LUT_OUT_VIDEO_RANGE:
+             return SynError(cube, "Unsupported format");
+ 
+             // Read and create tables
+         case SINUM:
+         case SDNUM:
+ 
+             if (shaper_size > 0) {
+ 
+                 cmsToneCurve* curves[3];
+                 cmsFloat32Number* shapers = (cmsFloat32Number*)_cmsMalloc(cube->ContextID, 3 * shaper_size * sizeof(cmsFloat32Number));
+                 if (shapers == NULL) return FALSE;
+ 
+                 for (i = 0; i < shaper_size; i++) {
+ 
+                     cmsFloat64Number nums[3];
+ 
+                     if (!ReadNumbers(cube, 3, nums)) return FALSE;
+ 
+                     shapers[i + 0]               = (cmsFloat32Number) ((nums[0] - domain_min[0]) / (domain_max[0] - domain_min[0]));
+                     shapers[i + 1 * shaper_size] = (cmsFloat32Number) ((nums[1] - domain_min[1]) / (domain_max[1] - domain_min[1]));
+                     shapers[i + 2 * shaper_size] = (cmsFloat32Number) ((nums[2] - domain_min[2]) / (domain_max[2] - domain_min[2]));
+                 }
+ 
+                 for (i = 0; i < 3; i++) {
+ 
+                     curves[i] = cmsBuildTabulatedToneCurveFloat(cube->ContextID, shaper_size,
+                         &shapers[i * shaper_size]);
+                     if (curves[i] == NULL) return FALSE;
+                 }
+ 
+                 *Shaper = cmsStageAllocToneCurves(cube->ContextID, 3, curves);
+ 
+                 cmsFreeToneCurveTriple(curves);
+             }
+ 
+             if (lut_size > 0) {
+ 
+                 int nodes = lut_size * lut_size * lut_size;
+ 
+                 cmsFloat32Number* lut_table = _cmsMalloc(cube->ContextID, nodes * 3 * sizeof(cmsFloat32Number));
+                 if (lut_table == NULL) return FALSE;
+ 
+                 for (i = 0; i < nodes; i++) {
+ 
+                     cmsFloat64Number nums[3];
+ 
+                     if (!ReadNumbers(cube, 3, nums)) return FALSE;
+ 
+                     lut_table[i * 3 + 2] = (cmsFloat32Number) ((nums[0] - domain_min[0]) / (domain_max[0] - domain_min[0]));
+                     lut_table[i * 3 + 1] = (cmsFloat32Number) ((nums[1] - domain_min[1]) / (domain_max[1] - domain_min[1]));
+                     lut_table[i * 3 + 0] = (cmsFloat32Number) ((nums[2] - domain_min[2]) / (domain_max[2] - domain_min[2]));
+                 }
+ 
+                 *CLUT = cmsStageAllocCLutFloat(cube->ContextID, lut_size, 3, 3, lut_table);
+                 _cmsFree(cube->ContextID, lut_table);
+             }
+ 
+             if (!Check(cube, SEOF, "Extra symbols found in file")) return FALSE;
+         }
+     }
+ 
+     return TRUE;
+ }
+ 
+ // Share the parser to read .cube format and create RGB devicelink profiles
+ cmsHPROFILE CMSEXPORT cmsCreateDeviceLinkFromCubeFileTHR(cmsContext ContextID, const char* cFileName)
+ {
+     cmsHPROFILE hProfile = NULL;
+     cmsIT8* cube = NULL;
+     cmsPipeline* Pipeline = NULL;
+     cmsStage* CLUT = NULL;
+     cmsStage* Shaper = NULL;
+     cmsMLU* DescriptionMLU = NULL;
+     char title[MAXSTR];
+ 
+     _cmsAssert(cFileName != NULL);
+ 
+     cube = (cmsIT8*) cmsIT8Alloc(ContextID);
+     if (!cube) return NULL;
+ 
+     cube->IsCUBE = TRUE;
+     cube->FileStack[0]->Stream = fopen(cFileName, "rt");
+ 
+     if (!cube->FileStack[0]->Stream) goto Done;
+ 
+     strncpy(cube->FileStack[0]->FileName, cFileName, cmsMAX_PATH - 1);
+     cube->FileStack[0]->FileName[cmsMAX_PATH - 1] = 0;
+ 
+     if (!ParseCube(cube, &Shaper, &CLUT, title)) goto Done;
+ 
+     // Success on parsing, let's create the profile
+     hProfile = cmsCreateProfilePlaceholder(ContextID);
+     if (!hProfile) goto Done;
+ 
+     cmsSetProfileVersion(hProfile, 4.4);
+ 
+     cmsSetDeviceClass(hProfile, cmsSigLinkClass);
+     cmsSetColorSpace(hProfile,  cmsSigRgbData);
+     cmsSetPCS(hProfile,         cmsSigRgbData);
+ 
+     cmsSetHeaderRenderingIntent(hProfile, INTENT_PERCEPTUAL);
+ 
+     // Creates a Pipeline to hold CLUT and shaper
+     Pipeline = cmsPipelineAlloc(ContextID, 3, 3);
+     if (Pipeline == NULL) goto Done;
+ 
+     // Populates the pipeline
+     if (Shaper != NULL) {
+         if (!cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, Shaper))
+             goto Done;
+     }
+ 
+     if (CLUT != NULL) {
+         if (!cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT))
+             goto Done;
+     }
+ 
+     // Propagate the description. We put no copyright because we know
+     // nothing on the copyrighted state of the .cube
+     DescriptionMLU = cmsMLUalloc(ContextID, 1);
+     if (!cmsMLUsetUTF8(DescriptionMLU, cmsNoLanguage, cmsNoCountry, title)) goto Done;
+ 
+     // Flush the tags
+     if (!cmsWriteTag(hProfile, cmsSigProfileDescriptionTag, DescriptionMLU)) goto Done;
+     if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, (void*)Pipeline)) goto Done;
+ 
+ Done:
+ 
+     if (DescriptionMLU != NULL)
+         cmsMLUfree(DescriptionMLU);
+ 
+     if (Pipeline != NULL)
+         cmsPipelineFree(Pipeline);
+ 
+     cmsIT8Free((cmsHANDLE) cube);
+ 
+     return hProfile;
+ }
+ 
+ cmsHPROFILE CMSEXPORT cmsCreateDeviceLinkFromCubeFile(const char* cFileName)
+ {
+     return cmsCreateDeviceLinkFromCubeFileTHR(NULL, cFileName);
+ }
< prev index next >