Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[Manta] r1844 - in trunk/Core: . Color


Chronological Thread 
  • From: sparker@sci.utah.edu
  • To: manta@sci.utah.edu
  • Subject: [Manta] r1844 - in trunk/Core: . Color
  • Date: Fri, 9 Nov 2007 17:43:08 -0700 (MST)

Author: sparker
Date: Fri Nov  9 17:42:57 2007
New Revision: 1844

Added:
   trunk/Core/Color/Spectrum.cc
   trunk/Core/Color/Spectrum.h
Modified:
   trunk/Core/CMakeLists.txt
   trunk/Core/Color/ColorSpace.h
   trunk/Core/Color/Conversion.h
   trunk/Core/Color/RGBColor.cc
   trunk/Core/Color/RGBColor.h
   trunk/Core/Color/RGBTraits.cc
   trunk/Core/Color/RGBTraits.h
Log:
Added abiltiy to specify a color as a spectral power distribution
Reorganized persistent I/O for colors - moved it into the color class insted 
of
the traits class.


Modified: trunk/Core/CMakeLists.txt
==============================================================================
--- trunk/Core/CMakeLists.txt   (original)
+++ trunk/Core/CMakeLists.txt   Fri Nov  9 17:42:57 2007
@@ -10,6 +10,8 @@
      Color/RGBTraits.cc
      Color/GrayColor.h
      Color/GrayColor.cc
+     Color/Spectrum.h
+     Color/Spectrum.cc
      Color/RegularColorMap.h
      Color/RegularColorMap.cc)
 SET (CORE_SOURCES ${CORE_SOURCES}

Modified: trunk/Core/Color/ColorSpace.h
==============================================================================
--- trunk/Core/Color/ColorSpace.h       (original)
+++ trunk/Core/Color/ColorSpace.h       Fri Nov  9 17:42:57 2007
@@ -6,6 +6,7 @@
 #include <Core/Color/GrayTraits.h>
 #include <Core/Color/RGBColor.h>
 #include <Core/Color/RGBTraits.h>
+#include <Core/Color/Spectrum.h>
 #include <Core/Math/Expon.h>
 #include <Core/Persistent/ArchiveElement.h>
 #include <Core/Persistent/MantaRTTI.h>
@@ -85,6 +86,9 @@
     explicit ColorSpace(const RGBColor& color) {
       Traits::convertFrom(data, color);
     }
+    explicit ColorSpace(const Spectrum& spectrum) {
+      Traits::convertFrom(data, spectrum);
+    }
 
     // This is what I originally did, but I didn't like the syntax.
     // This was fine:
@@ -284,13 +288,19 @@
         std::string str;
         archive->readwrite("data", str);
         RGBColor rgb;
-        if(RGBTraits::parseColor(rgb, str)){
+        Spectrum spectrum;
+        if(rgb.readPersistentString(str)){
           Traits::convertFrom(data.data, rgb);
+        } else if(spectrum.readPersistentString(str)){
+          Traits::convertFrom(data.data, spectrum);
         } else {
           throw SerializationError("Unknown color value: " + str);
         }
       } else {
-        Traits::readwrite(archive, data.data);
+        typename Traits::ColorType outcolor;
+        Traits::convertTo(outcolor, data.data);
+        std::string str = outcolor.writePersistentString();
+        archive->readwrite("data", str);
       }
     }
     static PersistentStorage::StorageHint storageHint() {

Modified: trunk/Core/Color/Conversion.h
==============================================================================
--- trunk/Core/Color/Conversion.h       (original)
+++ trunk/Core/Color/Conversion.h       Fri Nov  9 17:42:57 2007
@@ -4,12 +4,17 @@
 
 #include <Core/Color/GrayColor.h>
 #include <Core/Color/RGBColor.h>
+#include <Core/Color/Spectrum.h>
 
 namespace Manta {
   inline void convertColor(RGBColor& rgb, const GrayColor& gray)
   {
     float g = gray.grayValue();
     rgb = RGBColor(g, g, g);
+  }
+  inline void convertColor(RGBColor& rgb, const Spectrum& spectrum)
+  {
+    rgb = spectrum.getRGB();
   }
 }
 

Modified: trunk/Core/Color/RGBColor.cc
==============================================================================
--- trunk/Core/Color/RGBColor.cc        (original)
+++ trunk/Core/Color/RGBColor.cc        Fri Nov  9 17:42:57 2007
@@ -1,9 +1,12 @@
 
 #include <Core/Color/RGBColor.h>
+#include <Core/Color/ColorDB.h>
 
 #include <sgi_stl_warnings_off.h>
 #include <sstream>
 #include <string>
+#include <iomanip>
+#include <ctype.h>
 #include <sgi_stl_warnings_on.h>
 
 using namespace Manta;
@@ -13,4 +16,89 @@
   ostringstream out;
   out << "RGBColor("<<data[0]<<", "<<data[1]<<", "<<data[2]<<")";
   return out.str();
+}
+
+std::string RGBColor::writePersistentString() const
+{
+  // First, see if we can approximate the color with an rgb that is 
divisible by 256 so that
+  // we can use the HTML hex notation
+  bool hexworks = true;
+  int hex[3];
+  for(int i=0;i<3;i++){
+    if(data[i] < 0 || data[i] > 1){
+      hexworks = false;
+    } else {
+      hex[i] = (int)(data[0]*255 + 0.5);
+      if(hex[i]/255.0 != data[i])
+        hexworks = false;
+    }
+  }
+  ostringstream rep;
+  if(hexworks){
+    rep << "#";
+    for(int i=0;i<3;i++)
+      rep << setfill('0') << setbase(16) << setw(2) << hex[i];
+  } else {
+    rep << "rgb: " << data[0] << " " << data[1] << " " << data[2];
+  }
+  return rep.str();
+}
+
+static inline int hexvalue(char c){
+  if(c >= '0' && c <= '9')
+    return c-'0';
+  else if(c >= 'a' && c <= 'f')
+    return c-'a';
+  else if(c >= 'A' && c <= 'F')
+    return c-'A';
+  else
+    return 0;
+}
+
+bool RGBColor::readPersistentString(const std::string& str)
+{
+  if(str[0] == '#'){
+    // Parse html style hex string
+    std::string::size_type idx = 1;
+    while(idx < str.size() && ((str[idx] >= '0' && str[idx] <= '9') || 
(str[idx] >= 'a' && str[idx] <= 'f') || (str[idx] >= 'A' && str[idx] <= 'F')))
+      idx++;
+
+    if(idx == 7){
+      data[0] = (hexvalue(str[1])<<4) + hexvalue(str[2]);
+      data[1] = (hexvalue(str[3])<<4) + hexvalue(str[4]);
+      data[2] = (hexvalue(str[5])<<4) + hexvalue(str[6]);
+    } else if(idx == 4){
+      data[0] = (hexvalue(str[1])<<4) + hexvalue(str[1]);
+      data[1] = (hexvalue(str[2])<<4) + hexvalue(str[2]);
+      data[2] = (hexvalue(str[3])<<4) + hexvalue(str[3]);
+    } else {
+      return false;
+    }
+    while(idx < str.size() && !isspace(str[idx]))
+      idx++;
+    if(idx != str.size())
+      return false;
+
+    data[0] /= 255.;
+    data[1] /= 255.;
+    data[2] /= 255.;
+    return true;
+  } else if(str.substr(0, 4) == "rgb:"){
+    // RGB triple
+    std::istringstream in(str.substr(4));
+    in >> data[0] >> data[1] >> data[2];
+    if(!in)
+      return false;
+    return true;
+  } else if(ColorDB::getNamedColor(*this, str)){
+    // A named color
+    return true;
+  } else {
+    // Try to parse as an rgb triple
+    std::istringstream in(str);
+    in >> data[0] >> data[1] >> data[2];
+    if(!in)
+      return false;
+    return true;
+  }
 }

Modified: trunk/Core/Color/RGBColor.h
==============================================================================
--- trunk/Core/Color/RGBColor.h (original)
+++ trunk/Core/Color/RGBColor.h Fri Nov  9 17:42:57 2007
@@ -56,6 +56,8 @@
     }
 
     std::string toString() const;
+    std::string writePersistentString() const;
+    bool readPersistentString(const std::string& str);
     
   protected:
     float data[3];

Modified: trunk/Core/Color/RGBTraits.cc
==============================================================================
--- trunk/Core/Color/RGBTraits.cc       (original)
+++ trunk/Core/Color/RGBTraits.cc       Fri Nov  9 17:42:57 2007
@@ -1,11 +1,6 @@
 
 #include <Core/Color/RGBTraits.h>
 #include <Core/Color/ColorSpace.h>
-#include <Core/Color/ColorDB.h>
-#include <Core/Persistent/ArchiveElement.h>
-#include <sstream>
-#include <iomanip>
-#include <ctype.h>
 
 using namespace Manta;
 using namespace std;
@@ -13,93 +8,3 @@
 template<>
 bool MantaRTTI<ColorSpace<RGBTraits> >::force_initialize = 
MantaRTTI<ColorSpace<RGBTraits> >::registerClass();
 
-void RGBTraits::readwrite(ArchiveElement* archive, ComponentType data[3])
-{
-  // Only used for writing...
-
-  // First, see if we can approximate the color with an rgb that is 
divisible by 256 so that
-  // we can use the HTML hex notation
-  bool hexworks = true;
-  int hex[3];
-  for(int i=0;i<3;i++){
-    if(data[i] < 0 || data[i] > 1){
-      hexworks = false;
-    } else {
-      hex[i] = (int)(data[0]*255 + 0.5);
-      if(hex[i]/255.0 != data[i])
-        hexworks = false;
-    }
-  }
-  ostringstream rep;
-  if(hexworks){
-    rep << "#";
-    for(int i=0;i<3;i++)
-      rep << setfill('0') << setbase(16) << setw(2) << hex[i];
-  } else {
-    rep << "rgb: " << data[0] << " " << data[1] << " " << data[2];
-  }
-  string repstring = rep.str();
-  archive->readwrite("rgb", repstring);
-}
-
-static inline int hexvalue(char c){
-  if(c >= '0' && c <= '9')
-    return c-'0';
-  else if(c >= 'a' && c <= 'f')
-    return c-'a';
-  else if(c >= 'A' && c <= 'F')
-    return c-'A';
-  else
-    return 0;
-}
-
-bool RGBTraits::parseColor(RGBColor& result, const std::string& str)
-{
-  if(str[0] == '#'){
-    // Parse html style hex string
-    std::string::size_type idx = 1;
-    while(idx < str.size() && ((str[idx] >= '0' && str[idx] <= '9') || 
(str[idx] >= 'a' && str[idx] <= 'f') || (str[idx] >= 'A' && str[idx] <= 'F')))
-      idx++;
-
-    int r, g, b;
-    if(idx == 7){
-      r = (hexvalue(str[1])<<4) + hexvalue(str[2]);
-      g = (hexvalue(str[3])<<4) + hexvalue(str[4]);
-      b = (hexvalue(str[5])<<4) + hexvalue(str[6]);
-    } else if(idx == 4){
-      r = (hexvalue(str[1])<<4) + hexvalue(str[1]);
-      g = (hexvalue(str[2])<<4) + hexvalue(str[2]);
-      b = (hexvalue(str[3])<<4) + hexvalue(str[3]);
-    } else {
-      return false;
-    }
-    while(idx < str.size() && !isspace(str[idx]))
-      idx++;
-    if(idx != str.size())
-      return false;
-
-    result = RGBColor(r/255., g/255., b/255.);
-    return true;
-  } else if(str.substr(0, 4) == "rgb:"){
-    // RGB triple
-    std::istringstream in(str.substr(4));
-    float r,g,b;
-    in >> r >> g >> b;
-    if(!in)
-      return false;
-    result = RGBColor(r, g, b);
-    return true;
-  } else if(ColorDB::getNamedColor(result, str)){
-    // A named color
-    return true;
-  } else {
-    // Try to parse as an rgb triple
-    std::istringstream in(str);
-    float r,g,b;
-    in >> r >> g >> b;
-    if(!in)
-      return false;
-    result = RGBColor(r, g, b);
-    return true;
-  }
-}

Modified: trunk/Core/Color/RGBTraits.h
==============================================================================
--- trunk/Core/Color/RGBTraits.h        (original)
+++ trunk/Core/Color/RGBTraits.h        Fri Nov  9 17:42:57 2007
@@ -10,6 +10,7 @@
   class ArchiveElement;
   class RGBTraits {
   public:
+    typedef RGBColor ColorType;
     typedef float ComponentType;
     enum {NumComponents = 3};
 

Added: trunk/Core/Color/Spectrum.cc
==============================================================================
--- (empty file)
+++ trunk/Core/Color/Spectrum.cc        Fri Nov  9 17:42:57 2007
@@ -0,0 +1,177 @@
+
+#include <Core/Color/Spectrum.h>
+#include <Core/Exceptions/SerializationError.h>
+#include <Core/Math/MinMax.h>
+
+#include <sgi_stl_warnings_off.h>
+#include <sstream>
+#include <string>
+#include <iomanip>
+#include <ctype.h>
+#include <sgi_stl_warnings_on.h>
+
+using namespace Manta;
+using namespace std;
+using SCIRun::Min;
+
+typedef float MatchSample[4];
+
+// Stiles & Burch (1955) 2-deg color matching functions
+static MatchSample match[] = {
+  {390,  1.83970e-003, -4.53930e-004,  1.21520e-002},
+  {395,  4.61530e-003, -1.04640e-003,  3.11100e-002},
+  {400,  9.62640e-003, -2.16890e-003,  6.23710e-002},
+  {405,  1.89790e-002, -4.43040e-003,  1.31610e-001},
+  {410,  3.08030e-002, -7.20480e-003,  2.27500e-001},
+  {415,  4.24590e-002, -1.25790e-002,  3.58970e-001},
+  {420,  5.16620e-002, -1.66510e-002,  5.23960e-001},
+  {425,  5.28370e-002, -2.12400e-002,  6.85860e-001},
+  {430,  4.42870e-002, -1.99360e-002,  7.96040e-001},
+  {435,  3.22200e-002, -1.60970e-002,  8.94590e-001},
+  {440,  1.47630e-002, -7.34570e-003,  9.63950e-001},
+  {445, -2.33920e-003,  1.36900e-003,  9.98140e-001},
+  {450, -2.91300e-002,  1.96100e-002,  9.18750e-001},
+  {455, -6.06770e-002,  4.34640e-002,  8.24870e-001},
+  {460, -9.62240e-002,  7.09540e-002,  7.85540e-001},
+  {465, -1.37590e-001,  1.10220e-001,  6.67230e-001},
+  {470, -1.74860e-001,  1.50880e-001,  6.10980e-001},
+  {475, -2.12600e-001,  1.97940e-001,  4.88290e-001},
+  {480, -2.37800e-001,  2.40420e-001,  3.61950e-001},
+  {485, -2.56740e-001,  2.79930e-001,  2.66340e-001},
+  {490, -2.77270e-001,  3.33530e-001,  1.95930e-001},
+  {495, -2.91250e-001,  4.05210e-001,  1.47300e-001},
+  {500, -2.95000e-001,  4.90600e-001,  1.07490e-001},
+  {505, -2.97060e-001,  5.96730e-001,  7.67140e-002},
+  {510, -2.67590e-001,  7.01840e-001,  5.02480e-002},
+  {515, -2.17250e-001,  8.08520e-001,  2.87810e-002},
+  {520, -1.47680e-001,  9.10760e-001,  1.33090e-002},
+  {525, -3.51840e-002,  9.84820e-001,  2.11700e-003},
+  {530,  1.06140e-001,  1.03390e+000, -4.15740e-003},
+  {535,  2.59810e-001,  1.05380e+000, -8.30320e-003},
+  {540,  4.19760e-001,  1.05120e+000, -1.21910e-002},
+  {545,  5.92590e-001,  1.04980e+000, -1.40390e-002},
+  {550,  7.90040e-001,  1.03680e+000, -1.46810e-002},
+  {555,  1.00780e+000,  9.98260e-001, -1.49470e-002},
+  {560,  1.22830e+000,  9.37830e-001, -1.46130e-002},
+  {565,  1.47270e+000,  8.80390e-001, -1.37820e-002},
+  {570,  1.74760e+000,  8.28350e-001, -1.26500e-002},
+  {575,  2.02140e+000,  7.46860e-001, -1.13560e-002},
+  {580,  2.27240e+000,  6.49300e-001, -9.93170e-003},
+  {585,  2.48960e+000,  5.63170e-001, -8.41480e-003},
+  {590,  2.67250e+000,  4.76750e-001, -7.02100e-003},
+  {595,  2.80930e+000,  3.84840e-001, -5.74370e-003},
+  {600,  2.87170e+000,  3.00690e-001, -4.27430e-003},
+  {605,  2.85250e+000,  2.28530e-001, -2.91320e-003},
+  {610,  2.76010e+000,  1.65750e-001, -2.26930e-003},
+  {615,  2.59890e+000,  1.13730e-001, -1.99660e-003},
+  {620,  2.37430e+000,  7.46820e-002, -1.50690e-003},
+  {625,  2.10540e+000,  4.65040e-002, -9.38220e-004},
+  {630,  1.81450e+000,  2.63330e-002, -5.53160e-004},
+  {635,  1.52470e+000,  1.27240e-002, -3.16680e-004},
+  {640,  1.25430e+000,  4.50330e-003, -1.43190e-004},
+  {645,  1.00760e+000,  9.66110e-005, -4.08310e-006},
+  {650,  7.86420e-001, -1.96450e-003,  1.10810e-004},
+  {655,  5.96590e-001, -2.63270e-003,  1.91750e-004},
+  {660,  4.43200e-001, -2.62620e-003,  2.26560e-004},
+  {665,  3.24100e-001, -2.30270e-003,  2.15200e-004},
+  {670,  2.34550e-001, -1.87000e-003,  1.63610e-004},
+  {675,  1.68840e-001, -1.44240e-003,  9.71640e-005},
+  {680,  1.20860e-001, -1.07550e-003,  5.10330e-005},
+  {685,  8.58110e-002, -7.90040e-004,  3.52710e-005},
+  {690,  6.02600e-002, -5.67650e-004,  3.12110e-005},
+  {695,  4.14800e-002, -3.92740e-004,  2.45080e-005},
+  {700,  2.81140e-002, -2.62310e-004,  1.65210e-005},
+  {705,  1.91170e-002, -1.75120e-004,  1.11240e-005},
+  {710,  1.33050e-002, -1.21400e-004,  8.69650e-006},
+  {715,  9.40920e-003, -8.57600e-005,  7.43510e-006},
+  {720,  6.51770e-003, -5.76770e-005,  6.10570e-006},
+  {725,  4.53770e-003, -3.90030e-005,  5.02770e-006},
+  {730,  3.17420e-003, -2.65110e-005,  4.12510e-006}
+};
+
+float sample_scale[] = {1./206.327774, 1./94.4312286, 1./55.3023796};
+
+RGBColor Spectrum::getRGB() const
+{
+  // Integrate against the color matching curves
+  int nmatch = sizeof(match)/sizeof(MatchSample);
+  
+  int imatch = 0;
+  while(imatch+1 < nmatch && match[imatch+1][0] < samples[0])
+    imatch++;
+
+  int nsamples = samples.size();
+  int isample = 0;
+  while(isample+2 < nsamples && samples[isample+2] < match[imatch][0])
+    isample += 2;
+
+  float sum[3];
+  for(int i=0;i<3;i++)
+    sum[i] = 0;
+
+  float w0 = Min(match[imatch][0], samples[isample]);
+  imatch++; isample += 2;
+  for(;;){
+    float w1 = Min(match[imatch][0], samples[isample]);
+
+    float ma = (samples[isample+1] - samples[isample-1]) / (samples[isample] 
- samples[isample-2]);
+    float ba = samples[isample-1] - ma * samples[isample-2];
+    for(int j=0;j<3;j++){
+      float mb = (match[imatch][j+1] - match[imatch-1][j+1]) / 
(match[imatch][0] - match[imatch-1][0]);
+      float bb = match[imatch-1][j+1] - mb * match[imatch-1][0];
+      float integral = ma*mb           * (w1*w1*w1 - w0*w0*w0) * (1./3) + 
+                       (ba*mb + ma*bb) * (w1*w1 - w0*w0) * (1./2.) + 
+                       ba*bb           * (w1 - w0);
+      sum[j] += integral;
+    }
+
+    if(match[imatch][0] == w1){
+      imatch++;
+      if(imatch >= nmatch)
+        break;
+    }
+    if(samples[isample] == w1){
+      isample += 2;
+      if(isample >= nsamples)
+        break;
+    }
+    w0 = w1;
+  }
+  for(int j=0;j<3;j++)
+    sum[j] *= sample_scale[j];
+  return RGBColor(sum[0], sum[1], sum[2]);
+}
+
+std::string Spectrum::writePersistentString() const
+{
+  ostringstream str;
+  str << "spectrum:";
+  for(vector<float>::const_iterator iter = samples.begin(); iter != 
samples.end(); iter++)
+    str << ' ' << *iter;
+  return str.str();
+}
+
+bool Spectrum::readPersistentString(const std::string& str)
+{
+  if(str.substr(0, 9) == "spectrum:"){
+    // A spectrum
+    std::istringstream in(str.substr(9));
+    float f;
+    while(in >> f)
+      samples.push_back(f);
+    if(samples.size() % 2 != 0)
+      throw SerializationError("Illegal spectrum specification");
+    if(samples.size() < 4)
+      throw SerializationError("Illegal spectrum specification: too few 
samples");
+    float oldlambda = 0;
+    for(unsigned int i = 0; i < samples.size(); i+=2) {
+      float lambda = samples[i];
+      if(lambda < oldlambda)
+        throw SerializationError("Spectrum wavelengths must increase 
monotonically");
+      oldlambda = lambda;
+    }
+    return true;
+  } else {
+    return false;
+  }
+}

Added: trunk/Core/Color/Spectrum.h
==============================================================================
--- (empty file)
+++ trunk/Core/Color/Spectrum.h Fri Nov  9 17:42:57 2007
@@ -0,0 +1,42 @@
+
+#ifndef Manta_Core_Spectrum_h
+#define Manta_Core_Spectrum_h
+
+#include <sgi_stl_warnings_off.h>
+#include <Core/Color/RGBColor.h>
+#include <string>
+#include <vector>
+#include <sgi_stl_warnings_on.h>
+
+namespace Manta {
+  class Spectrum {
+  public:
+    Spectrum()
+    {
+    }
+
+    Spectrum(const std::vector<float>& samples)
+      : samples(samples)
+    {
+    }
+    
+    Spectrum(const Spectrum& copy)
+      : samples(copy.samples)
+    {
+    }
+
+    ~Spectrum() {
+    }
+
+    std::string toString() const;
+
+    RGBColor getRGB() const;
+    std::string writePersistentString() const;
+    bool readPersistentString(const std::string& str);
+    
+  protected:
+    std::vector<float> samples;
+  };
+}
+
+#endif




  • [Manta] r1844 - in trunk/Core: . Color, sparker, 11/09/2007

Archive powered by MHonArc 2.6.16.

Top of page