Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

colorlookup.h

Go to the documentation of this file.
00001 
00007 #ifndef __COLORLOOKUP_H__
00008 #define __COLORLOOKUP_H__
00009 
00010 #include <cassert>
00011 #include <algorithm>
00012 #include <vector>
00013 
00014 #include "pixel.h"
00015 #include "scale.h"
00016 
00017 #ifndef NO_VALGEN_STRINGS
00018 /* Optional: support for constructing from a string specification */
00019 #include <string>
00020 using std::string;
00021 #include "stringparser.h"
00022 #include "msg.h"
00023 #endif
00024 
00025 namespace  Plot {
00026 
00027 
00028 
00029 /******************************************************************************/
00030 /* ColorLookup class hierarchy                                                */
00031 /******************************************************************************/
00032 
00033 
00039 template<class PixelType=Plot::RGBPixel<>, class Scale=Scale::Linear<double> >
00040 class ColorLookup {
00041 public:
00042   virtual ~ColorLookup() { }
00043 
00045   ColorLookup(const Scale& scale=default_scale) : fn(scale) { }
00046   
00050   virtual PixelType operator() (const double mag) const
00051     {  return lookup(fn(mag));  }
00052 
00053 protected:
00054   typedef Scale ScaleType;
00055   static ScaleType default_scale;
00056   
00057 private:
00058   Scale fn;
00059 
00061   virtual PixelType lookup(const Bounded::Magnitude mag) const=0;
00062 };
00063 
00064 
00065 /* Static variables */
00066 template<class PixelType, class Scale>
00067 typename ColorLookup<PixelType,Scale>::ScaleType ColorLookup<PixelType,Scale>::default_scale;
00068 
00069 
00070 
00072 template<class PixelType=Plot::RGBPixel<>, class Scale=Scale::Linear<double> >
00073 class SingleColorLookup : public ColorLookup<PixelType,Scale> {
00074 public:
00075   virtual ~SingleColorLookup() { }
00076   SingleColorLookup(Bounded::Magnitude hue=0.0, Bounded::Magnitude sat=0.0, Bounded::Magnitude val=0.5)
00077     : h(hue), s(sat), v(val) {  }
00078     
00079 #ifndef NO_VALGEN_STRINGS
00080   SingleColorLookup(StringArgs& args)
00081     : h(args.next(0.0)), s(args.next(0.0)), v(args.next(0.5)) {  }
00082 #endif
00083   
00084 private:
00085   virtual PixelType lookup(const Bounded::Magnitude) const
00086     {  return PixelType(HSVPixel<>(h,s,v));  }
00087   
00088   Bounded::Magnitude h,s,v;
00089 };
00090 
00091 
00092 
00094 template<class PixelType=Plot::RGBPixel<>, class Scale=Scale::Linear<double> >
00095 class HueColorLookup : public ColorLookup<PixelType,Scale> {
00096 public:
00097   virtual ~HueColorLookup() { }
00098   HueColorLookup(Bounded::Magnitude sat=1.0, Bounded::Magnitude val=1.0,
00099                  const Scale& scale=default_scale)
00100     : ColorLookup<PixelType,Scale>(scale), s(sat), v(val) {  }
00101     
00102 #ifndef NO_VALGEN_STRINGS
00103   HueColorLookup(StringArgs& args, const Scale& scale=default_scale)
00104     : ColorLookup<PixelType,Scale>(scale), s(args.next(1.0)), v(args.next(1.0)) {  }
00105 #endif
00106   
00107 private:
00108   virtual PixelType lookup(const Bounded::Magnitude mag) const
00109     {  return PixelType(HSVPixel<>(mag,s,v));  }
00110   
00111   Bounded::Magnitude s,v;
00112 };
00113 
00114 
00115 
00117 template<class PixelType=Plot::RGBPixel<>, class Scale=Scale::Linear<double> >
00118 class SaturationColorLookup : public ColorLookup<PixelType,Scale> {
00119 public:
00120   virtual ~SaturationColorLookup() { }
00121   SaturationColorLookup(Bounded::Magnitude hue=0.0, Bounded::Magnitude val=1.0,
00122                         const Scale& scale=default_scale)
00123     : ColorLookup<PixelType,Scale>(scale), h(hue), v(val) {  }
00124     
00125 #ifndef NO_VALGEN_STRINGS
00126   SaturationColorLookup(StringArgs& args, const Scale& scale=default_scale)
00127     : ColorLookup<PixelType,Scale>(scale), h(args.next(0.0)), v(args.next(1.0)) {  }
00128 #endif
00129   
00130 private:
00131   virtual PixelType lookup(const Bounded::Magnitude mag) const 
00132     {  return PixelType(HSVPixel<>(h,mag,v));  }
00133 
00134   Bounded::Magnitude h,v;
00135 };
00136 
00137 
00138 
00140 template<class PixelType=Plot::RGBPixel<>, class Scale=Scale::Linear<double> >
00141 class ValueColorLookup : public ColorLookup<PixelType,Scale> {
00142 public:
00143   virtual ~ValueColorLookup() { }
00144   ValueColorLookup(Bounded::Magnitude hue=0.0, Bounded::Magnitude sat=0.0,
00145                    const Scale& scale=default_scale)
00146     : ColorLookup<PixelType,Scale>(scale), h(hue), s(sat) {  }
00147     
00148 #ifndef NO_VALGEN_STRINGS
00149   ValueColorLookup(StringArgs& args, const Scale& scale=default_scale)
00150     : ColorLookup<PixelType,Scale>(scale), h(args.next(0.0)), s(args.next(0.0)) {  }
00151 #endif
00152   
00153 private:
00154   virtual PixelType lookup(const Bounded::Magnitude mag) const
00155     {  return PixelType(HSVPixel<>(h,s,mag));  }
00156 
00157   Bounded::Magnitude h,s;
00158 };
00159 
00160 
00161 
00171 template<class PixelType=Plot::RGBPixel<>, class Scale=Scale::Linear<double> >
00172 class SpecifiedHueLookup : public ColorLookup<PixelType,Scale> {
00173 public:
00174   virtual ~SpecifiedHueLookup() { }
00175   SpecifiedHueLookup(Bounded::Magnitude hue=0.0,
00176                      Bounded::Magnitude confidence=1.0,
00177                      bool paper_based_colors=false,
00178                      const Scale& scale=default_scale)
00179     : ColorLookup<PixelType,Scale>(scale), h(hue), c(confidence) {  }
00180   
00181 #ifndef NO_VALGEN_STRINGS
00182   SpecifiedHueLookup(StringArgs& args, 
00183                      bool paper_based_colors=false,
00184                      Bounded::Magnitude default_hue=0.0,
00185                      const Scale& scale=default_scale)
00186     : ColorLookup<PixelType,Scale>(scale), h(args.next(default_hue)), c(args.next(1.0)),
00187     paper_based(paper_based_colors) {  }
00188 #endif
00189   
00190 private:
00191   virtual PixelType lookup(const Bounded::Magnitude mag) const {
00192     return (paper_based?
00193             PixelType(HSVPixel<>(h,mag,std::max(1.0-mag,c))) : 
00194             PixelType(HSVPixel<>(h,c,mag)));
00195   }
00196 
00197   Bounded::Magnitude h,c;
00198   const bool paper_based;
00199 };
00200 
00201 
00202 
00212 template<class PixelType=Plot::RGBPixel<>, class Scale=Scale::Linear<double> >
00213 class ColorLookupTable : public ColorLookup<PixelType,Scale> {
00214 protected:
00215   typedef std::vector<PixelType> Table;
00216 
00217 public:
00218   ColorLookupTable(size_t numcolors,const Scale& scale=default_scale)
00219     : ColorLookup<PixelType,Scale>(scale), colors(numcolors), valid(true) { }
00220 
00221 #ifndef NO_VALGEN_STRINGS
00222 
00234   ColorLookupTable(const string& spec_="", size_t numcolors=0, const Scale& scale=default_scale)
00235     : ColorLookup<PixelType,Scale>(scale), colors(numcolors>0?numcolors:252), valid(true) {
00236 
00237     /* If empty, uses a default specification */
00238     const string spec      = (spec_.empty()? string("KRYW") : spec_);
00239     const size_t steps     = spec.length();
00240     const size_t stepsize  = size_t(colors.size()/(steps>1 ? (steps-1) : 1));
00241     size_t start,i;
00242     for (i=0,start=0; i<steps-1; i++,start+=stepsize)
00243       interpolate(start, start+stepsize,color(spec[i]), color(spec[i+1]));
00244     interpolate(start, colors.size(),color(spec[i]), color(spec[steps-1]));
00245   }
00246 #endif
00247 
00248   virtual ~ColorLookupTable() { }
00249 
00251   bool is_valid() {  return valid;  }
00252   
00253 private:  
00254   virtual PixelType lookup(const Bounded::Magnitude mag) const
00255     {  return colors[Generic::crop(0,int(colors.size()-1),int(mag*(colors.size()-1)))];  }
00256 
00257 protected:
00258   Table colors;
00259   bool  valid;
00260 
00264   void interpolate(const size_t start, const size_t finish,
00265                    const PixelType& startcolor, const PixelType& finishcolor) {
00266     assert (start<=finish);
00267     
00268     const size_t num_vals = size_t(finish-start);
00269     const double division = (num_vals!=0 ? 1.0/num_vals : 0);
00270     
00271     const double rs       = startcolor.red();
00272     const double gs       = startcolor.green();
00273     const double bs       = startcolor.blue();
00274     
00275     const double rinc     = division*(finishcolor.red()   - startcolor.red());
00276     const double ginc     = division*(finishcolor.green() - startcolor.green());
00277     const double binc     = division*(finishcolor.blue()  - startcolor.blue());
00278     
00279     for(size_t i=0; i<num_vals; i++)
00280       colors[start+i]=PixelType(rs+rinc*i,gs+ginc*i,bs+binc*i);
00281   }
00282 
00283   
00286   PixelType color(const char c) {
00287     PixelType p;
00288     const double h=0.5;
00289     switch (c) {
00290     case 'R': p=PixelType(1,0,0); break;   case 'r': p=PixelType(h,0,0); break;  /* Red     */
00291     case 'Y': p=PixelType(1,1,0); break;   case 'y': p=PixelType(h,h,0); break;  /* Yellow  */
00292     case 'G': p=PixelType(0,1,0); break;   case 'g': p=PixelType(0,h,0); break;  /* Green   */
00293     case 'C': p=PixelType(0,1,1); break;   case 'c': p=PixelType(0,h,h); break;  /* Cyan    */
00294     case 'B': p=PixelType(0,0,1); break;   case 'b': p=PixelType(0,0,h); break;  /* Blue    */
00295     case 'M': p=PixelType(1,0,1); break;   case 'm': p=PixelType(h,0,h); break;  /* Magenta */
00296     case 'W': p=PixelType(1,1,1); break;   case 'w': p=PixelType(h,h,h); break;  /* White   */
00297     case 'K': p=PixelType(0,0,0); break;   case 'k': p=PixelType(0,0,0); break;  /* Black   */
00298     default: valid=false; /* Set error flag if no match */
00299     }
00300     return p;
00301   }
00302 };
00303 
00304  
00305  
00308 template<class PixelType=Plot::RGBPixel<>, class Scale=Scale::Linear<double> >
00309 class KRYWColorLookup : public ColorLookupTable<PixelType,Scale> {
00310 public:
00311   virtual ~KRYWColorLookup() { }
00312   KRYWColorLookup(size_t numcolors=0, const Scale& scale=default_scale)
00313     : ColorLookupTable<PixelType,Scale>((numcolors>0?numcolors:252),scale) {
00314     const size_t step   = size_t(colors.size()/3);
00315     interpolate(0,      step,          PixelType(0,0,0), PixelType(1,0,0));
00316     interpolate(step,   2*step,        PixelType(1,0,0), PixelType(1,1,0));
00317     interpolate(2*step, colors.size(), PixelType(1,1,0), PixelType(1,1,1));
00318   }
00319 };
00320  
00321 
00322 
00323 /******************************************************************************/
00324 /* ColorLookupFactory                                                         */
00325 /******************************************************************************/
00326 
00328 #ifndef NO_VALGEN_STRINGS
00329 template<class PixelType=Plot::RGBPixel<>, class Scale=Scale::Linear<double> >
00330 class ColorLookupFactory {
00331   bool paper_based;
00332   Bounded::Magnitude default_hue;
00333   
00334 public:
00335   typedef ColorLookup<PixelType> result_type;
00336   virtual ~ColorLookupFactory() {  }
00337 
00338   ColorLookupFactory(bool paper_based_colors=false,
00339                      Bounded::Magnitude default_single_hue=0)
00340     : paper_based(paper_based_colors), default_hue(default_single_hue) {  }
00341   
00343   virtual result_type* operator() (string specification) const {
00344     /* Construct argument list */
00345     StringParser sp;
00346     StringArgs arglist(sp, specification);
00347     const string name=arglist.next(string(""));
00348     bool warned=false; /* Prevents multiple warnings */
00349     
00350     /* Scale to flip the value for some ColorLookup types */
00351     const Scale  scale=Scale((paper_based? -1.0 : 1.0),
00352                              (paper_based?  1.0 : 0.0));
00353     result_type* clu=0;
00354 
00355     if      (name=="Hue")            clu = new HueColorLookup<PixelType>(arglist);
00356     else if (name=="Saturation")     clu = new SaturationColorLookup<PixelType>(arglist);
00357     else if (name=="Value")          clu = new ValueColorLookup<PixelType>(arglist);
00358     else if (name=="Grayscale")      clu = new ValueColorLookup<PixelType>(arglist,scale);
00359     else if (name=="SpecifiedColor") clu = new SingleColorLookup<PixelType>(arglist);
00360     else if (name=="SpecifiedHue")   clu = new SpecifiedHueLookup<PixelType>(arglist,paper_based,default_hue);
00361     
00362     else if (name=="Cold")           clu = new ColorLookupTable<PixelType>(paper_based? "WBC"      : "KBCW");
00363     else if (name=="Cool")           clu = new ColorLookupTable<PixelType>(paper_based? "WbBC"     : "KBC");
00364     else if (name=="Warm")           clu = new ColorLookupTable<PixelType>(paper_based? "WrRY"     : "KRY");
00365     else if (name=="Hot")            clu = new ColorLookupTable<PixelType>(paper_based? "WRY"      : "KRYW");
00366     else if (name=="CoolWarm")       clu = new ColorLookupTable<PixelType>(paper_based? "CBbWrRY"  : "CBKRY");
00367     else if (name=="ColdHot")        clu = new ColorLookupTable<PixelType>(paper_based? "CBWRY"    : "WCBKRYW");
00368     else if (name=="BlueRed")        clu = new ColorLookupTable<PixelType>(paper_based? "BWR"      : "BKR");
00369 
00370     /* The name RYW is a misnomer, and is only for backwards compatibility */
00371     else if (name=="RYW")            clu = new ColorLookupTable<PixelType>(paper_based? "WRY"      : "KRYW");
00372 
00373     else { /* Assume it's a specification for an interpolated ColorLookupTable */
00374       ColorLookupTable<PixelType>*   c   = new ColorLookupTable<PixelType>(name);
00375       if (c->is_valid())             clu = c;
00376       else {
00377         error("ColorLookup: Unknown or invalid type `" + name + "'");
00378         warned=true;
00379       }
00380     }
00381     
00382     if (!warned && !arglist.empty())
00383       error("ColorLookup: Unused arguments: `" + arglist.stringrep() + "'");
00384     
00385     /* Use default value if none yet defined */
00386     if (!clu) clu = new KRYWColorLookup<PixelType>(0,scale);
00387     return clu;
00388   }
00389   
00390   virtual void error(const string& s) const {
00391     Msg::LevelHandler<>* mh = Msg::LevelHandler<>::default_instance();
00392     if (mh) (*mh)(Msg::Error,s);
00393   }
00394 };
00395 #endif /* NO_VALGEN_STRINGS */
00396 
00397 
00398 
00400 #define RYWColorLookup KRYWColorLookup
00401 
00402 
00403 
00404 } /* namespace Plot */
00405 #endif /* __COLORLOOKUP_H__ */

Generated on Mon Jan 20 02:35:44 2003 for RF-LISSOM by doxygen1.3-rc2