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

pixel.h

Go to the documentation of this file.
00001 
00007 #ifndef __PIXEL_H__
00008 #define __PIXEL_H__
00009 
00010 #include <cmath>
00011 #include "mathconstants.h"
00012 
00013 // Uses roundabout path to the current directory to avoid Cray C bug
00014 #include "../src/boundednumber.h"
00015 
00016 
00018 namespace  Plot {
00019 
00020 
00021 /******************************************************************************/
00022 /* Pixel classes                                                              */
00023 /******************************************************************************/
00024 
00025 
00027 class Pixel {
00028 public:
00030   Pixel() : transparent(true) {  }
00031   
00033   Pixel(bool visible) : transparent(!visible) {  }
00034   
00036   Pixel(const Pixel& other) : transparent(other.transparent)  {  };
00037 
00039   bool istransparent() {  return transparent;  }
00040   
00042   void show() {  transparent=false;  }
00043   
00045   void hide() {  transparent=true;  }
00046 
00048   typedef Bounded::Integer<unsigned char> IComponent;
00049   
00051   typedef Bounded::Float<  float,1,0,Bounded::Crop<Bounded::LargeFloat> > FComponent;
00052 
00054   typedef Bounded::Float<  float,1,0,Bounded::Wrap<Bounded::LargeFloat> > HueComponent;
00055 
00056 private:
00057   bool transparent; 
00058 };
00059 
00060 
00061   
00062 /* Forward declarations to allow HSVPixel and RGBPixel to convert to
00063    and from one another
00064 */
00065 template<class>       class RGBPixel;
00066 template<class,class> class HSVPixel;
00067 
00068  
00069   
00071 template<class Component=Pixel::IComponent>
00072 class RGBPixel : public Pixel
00073 {
00074   typedef RGBPixel self;
00075   
00076 public:
00080   RGBPixel() : Pixel(), r(0), g(0), b(0) {  }
00081   
00088   RGBPixel(FComponent value) : Pixel(), r(value), g(value), b(value) {  }
00089   
00091   RGBPixel(FComponent red, FComponent green, FComponent blue, bool visible=true) : Pixel(visible),
00092     r(red), g(green), b(blue) {  }
00093   
00095   RGBPixel(const self& other)
00096     : Pixel(other), r(other.r), g(other.g), b(other.b)  {  }
00097   
00099   template<class OComponent, class OHComponent>
00100   RGBPixel(const HSVPixel<OComponent,OHComponent>& O);
00102   
00105   Bounded::Magnitude red()   const {  return r.mag();  } 
00106   Bounded::Magnitude green() const {  return g.mag();  } 
00107   Bounded::Magnitude blue()  const {  return b.mag();  } 
00109   
00111   self operator+= (const self &B) 
00112     {  r=r+B.r; g=g+B.g; b=b+B.b;  }
00113 
00115   self& operator*=(const Bounded::LargeFloat m)
00116     {  r*=m; g*=m; b*=m; return *this; }
00117 
00120   
00122   std::ostream& put(std::ostream& s) const
00123   {  return s << "(" << red() << "," << green() << "," << blue() << ")";  }
00124   
00126   self operator+(const self& o) {
00127     self tmp;
00128     tmp.r=r+o.r;
00129     tmp.g=g+o.g;
00130     tmp.b=b+o.b;
00131     return tmp;
00132   }
00133 
00136   template<class OutputType>
00137   void write_binary(std::ostream& s, OutputType max_val) const {
00138     s.put(OutputType(max_val*red()));
00139     s.put(OutputType(max_val*green()));
00140     s.put(OutputType(max_val*blue()));
00141   }
00143   
00144 private:
00145   Component r,g,b;
00146 };
00147 
00148 
00149 
00151 template<class Component>
00152 std::ostream& operator<<(std::ostream& s, const RGBPixel<Component>& o)
00153   {  return o.put(s);  }
00154 
00155  
00156 
00158 template<class Component=Pixel::FComponent, class HComponent=Pixel::HueComponent>
00159 class HSVPixel : public Pixel
00160 {
00161 public:
00165   HSVPixel() : Pixel(), h(0), s(0), v(0) {  }
00166   
00168   HSVPixel(HComponent hue, Component saturation, Component value)
00169     : Pixel(true), h(hue), s(saturation), v(value)  {  }
00170   
00172   HSVPixel(const HSVPixel& other)
00173     : Pixel(other), h(other.h), s(other.s), v(other.v)  {  }
00174   
00176   template<class OComponent>  
00177   HSVPixel(const RGBPixel<OComponent>& other);
00179   
00182   Bounded::Magnitude hue()        const {  return h.mag();  } 
00183   Bounded::Magnitude saturation() const {  return s.mag();  } 
00184   Bounded::Magnitude value()      const {  return v.mag();  } 
00186   
00188   std::ostream& put(std::ostream& s)
00189   {  return s << "(" << hue() << "," << saturation() << "," << value() << ")";  }
00190 
00193   static int reversed_color_order;
00194   
00195 private:
00196   HComponent h;
00197   Component  s,v;
00198 };
00199 
00200 
00201 /* Static variables */
00202 template<class Component, class HComponent>
00203 int HSVPixel<Component,HComponent>::reversed_color_order=false;
00204 
00205 
00207 template<class Component>
00208 std::ostream& operator<<(std::ostream& s, const HSVPixel<Component>& o)
00209 {  return o.put(s);  }
00210 
00211 
00217 template<class Component>
00218 template<class OComponent, class OHComponent>
00219 RGBPixel<Component>::RGBPixel(const HSVPixel<OComponent,OHComponent>& other) : Pixel(other)
00220 {
00221   int    j;
00222   double rd, gd, bd;
00223   double f, p, q, T;
00224   double hue;
00225   
00226   const double h=(HSVPixel<OComponent,OHComponent>::reversed_color_order?
00227                   1-other.hue() : other.hue());
00228   const double s=other.saturation();
00229   const double v=other.value();
00230   
00231   /* convert HSV back to RGB */
00232   if (s==0.0) { rd = v;  gd = v;  bd = v; }
00233   else {
00234     /* hue ranges [0,6) */
00235     hue = h * 6.0;
00236     
00237     j = (int) floor(hue);
00238     if (j<0) j=0;          /* either h or floor seem to go neg on some sys */
00239     f = hue - j;
00240     p = v * (1-s);
00241     q = v * (1 - (s*f));
00242     T = v * (1 - (s*(1 - f)));
00243     
00244     switch (j) {
00245     case 0:  rd = v;  gd = T;  bd = p;  break;
00246     case 1:  rd = q;  gd = v;  bd = p;  break;
00247     case 2:  rd = p;  gd = v;  bd = T;  break;
00248     case 3:  rd = p;  gd = q;  bd = v;  break;
00249     case 4:  rd = T;  gd = p;  bd = v;  break;
00250     case 5:  rd = v;  gd = p;  bd = q;  break;
00251     default: rd = v;  gd = T;  bd = p;  break;  /* never happen */
00252     }
00253   }
00254   
00255   r = Component(Bounded::LargeInt(floor( rd*r.Max + 0.5 )));
00256   g = Component(Bounded::LargeInt(floor( gd*g.Max + 0.5 )));
00257   b = Component(Bounded::LargeInt(floor( bd*b.Max + 0.5 )));
00258 }
00259 
00260 
00261 
00268 template<class Component, class HComponent>
00269 template<class OComponent>
00270 HSVPixel<Component,HComponent>::HSVPixel(const RGBPixel<OComponent>& other) : Pixel(other)
00271 {
00272   double r = other.red();
00273   double g = other.green();
00274   double b = other.blue();
00275 
00276   double hh=0;
00277   
00278   double maxval = std::max(std::max(r,g),b);
00279   double minval = std::min(std::min(r,g),b);
00280 
00281   /* Value */
00282   v = maxval;
00283 
00284   /* Saturation */
00285   s = (maxval == 0.0) ? 0.0 : ((maxval-minval)/maxval);
00286   
00287   /* Hue */
00288   if (s.mag() == 0.0)
00289     hh = 0;
00290   else {
00291     double delt = maxval - minval;
00292     
00293     if (r == maxval)
00294       hh =       (g - b)/delt; /* Between yellow and magenta */
00295     
00296     else if (g == maxval)
00297       hh = 2.0 + (b - r)/delt; /* Between cyan and yellow    */
00298     
00299     else if (b  == maxval)
00300       hh = 4.0 + (r - g)/delt; /* Between magenta and cyan   */
00301     
00302     /* Convert to degrees (disabled) */
00303     /* *h *= 60; if (*h < 0.0) *h += 360; */
00304     
00305     /* Scale to Max */
00306     hh *= (60.0/360.0); if (hh < 0.0) hh = hh+h.Max;
00307   }
00308   h = (reversed_color_order? 1.0-hh : hh);
00309 }
00310 
00311 
00312 
00320 template<class HSVPixelType=HSVPixel<> >
00321 class PixelAverage {
00322 private:
00323   double valtot, colorx, colory, count;
00324 
00325 public:
00326   PixelAverage() : valtot(0), colorx(0), colory(0), count(0)  { }
00327 
00329   void operator+=(HSVPixelType p) {
00330     const double angle = 2*(Math::pi)*p.hue();
00331     const double mag   = p.saturation();
00332     colorx += mag * cos(angle);
00333     colory += mag * sin(angle);
00334     valtot += p.value();
00335     count++;
00336   }
00337   
00339   HSVPixelType operator() () const {
00340     const Bounded::Magnitude hue = (colorx? atan2(colory,colorx)/2/(Math::pi) : 0.0);
00341     const Bounded::Magnitude sat = (count? sqrt(colorx*colorx+colory*colory)/count : 0.0);
00342     const Bounded::Magnitude val = (count? valtot/count : 0.0);
00343     return HSVPixel<>(hue,sat,val);
00344   }
00345 };
00346 
00347     
00348 
00358 template<class HSVPixelType>  
00359 RGBPixel<>  contrasting_color( HSVPixelType prevailing_color) {
00360   const Bounded::Magnitude  val = prevailing_color.value();
00361   if      (val >= 0.75) return RGBPixel<>(0,0,0); /* bright background */
00362   else if (val <  0.25) return RGBPixel<>(1,1,1); /* dark background   */
00363   else                  return RGBPixel<>(0,0,1); /* medium background */
00364 }
00365 
00366   
00367 } /* namespace Plot */
00368 #endif /* __PIXEL_H__ */

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