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 
00012 // Uses roundabout path to the current directory to avoid Cray C bug
00013 #include "../src/boundednumber.h"
00014 
00016 namespace  Plot {
00017 
00018 
00019 /******************************************************************************/
00020 /* Pixel classes                                                              */
00021 /******************************************************************************/
00022 
00023 
00025 class Pixel {
00026 public:
00028   Pixel() : transparent(true) {  }
00029   
00031   Pixel(bool visible) : transparent(!visible) {  }
00032   
00034   Pixel(const Pixel& other) : transparent(other.transparent)  {  };
00035 
00037   bool istransparent() {  return transparent;  }
00038   
00040   void show() {  transparent=false;  }
00041   
00043   void hide() {  transparent=true;  }
00044 
00046   typedef Bounded::Integer<unsigned char> IComponent;
00047   
00049   typedef Bounded::Float<  float,1,0,Bounded::Crop<Bounded::LargeFloat> > FComponent;
00050 
00052   typedef Bounded::Float<  float,1,0,Bounded::Wrap<Bounded::LargeFloat> > HueComponent;
00053   
00054 private:
00055   bool transparent; 
00056 };
00057 
00058 
00059 
00060 /* Forward declarations to allow HSVPixel and RGBPixel to convert to
00061    and from one another
00062 */
00063 template<class>       class RGBPixel;
00064 template<class,class> class HSVPixel;
00065 
00066  
00067   
00069 template<class Component=Pixel::IComponent>
00070 class RGBPixel : public Pixel
00071 {
00072   typedef RGBPixel self;
00073   
00074 public:
00078   RGBPixel() : Pixel(), r(0), g(0), b(0) {  }
00079   
00086   RGBPixel(FComponent value) : Pixel(), r(value), g(value), b(value) {  }
00087   
00089   RGBPixel(FComponent red, FComponent green, FComponent blue, bool visible=true) : Pixel(visible),
00090     r(red), g(green), b(blue) {  }
00091   
00093   RGBPixel(const self& other)
00094     : Pixel(other), r(other.r), g(other.g), b(other.b)  {  }
00095   
00097   template<class OComponent, class OHComponent>
00098   RGBPixel(const HSVPixel<OComponent,OHComponent>& O);
00100   
00103   Bounded::Magnitude red()   const {  return r.mag();  } 
00104   Bounded::Magnitude green() const {  return g.mag();  } 
00105   Bounded::Magnitude blue()  const {  return b.mag();  } 
00107   
00109   self operator+= (const self &B) 
00110     {  r=r+B.r; g=g+B.g; b=b+B.b;  }
00111 
00113   self& operator*=(const Bounded::LargeFloat m)
00114     {  r*=m; g*=m; b*=m; return *this; }
00115 
00118   
00120   template<class OComponent>
00121   friend ostream& operator<<(ostream& s, const RGBPixel<OComponent>& o);
00122 
00123   template<class OComponent>
00124   friend RGBPixel<OComponent> operator+(const RGBPixel<OComponent>& A, const RGBPixel<OComponent>& B);
00125 
00128   template<class OutputType>
00129   void write_binary(ostream& s, OutputType max_val) {
00130     s.put(OutputType(max_val*red()));
00131     s.put(OutputType(max_val*green()));
00132     s.put(OutputType(max_val*blue()));
00133   }
00135   
00136 private:
00137   Component r,g,b;
00138 };
00139 
00140 
00141 
00143 template<class Component>
00144 ostream& operator<<(ostream& s, const RGBPixel<Component>& o)
00145   {  return cout << "(" << o.red() << "," << o.green() << "," << o.blue() << ")";  }
00146 
00147  
00148 
00150 template <class Component>
00151        RGBPixel<Component> operator+
00152 (const RGBPixel<Component> &A,
00153  const RGBPixel<Component> &B) {
00154        RGBPixel<Component> tmp;
00155   tmp.r=A.r+B.r;
00156   tmp.g=A.g+B.g;
00157   tmp.b=A.b+B.b;
00158   return tmp;
00159 }
00160 
00161 
00162 
00164 template<class Component=Pixel::FComponent, class HComponent=Pixel::HueComponent>
00165 class HSVPixel : public Pixel
00166 {
00167 public:
00171   HSVPixel() : Pixel(), h(0), s(0), v(0) {  }
00172   
00174   HSVPixel(HComponent hue, Component saturation, Component value)
00175     : Pixel(true), h(hue), s(saturation), v(value)  {  }
00176   
00178   HSVPixel(const HSVPixel& other)
00179     : Pixel(other), h(other.h), s(other.s), v(other.v)  {  }
00180   
00182   template<class OComponent>  
00183   HSVPixel(const RGBPixel<OComponent>& other);
00185   
00188   Bounded::Magnitude hue()        const {  return h.mag();  } 
00189   Bounded::Magnitude saturation() const {  return s.mag();  } 
00190   Bounded::Magnitude value()      const {  return v.mag();  } 
00192   
00194   template<class OComponent>
00195   friend ostream& operator<<(ostream& s, const HSVPixel<OComponent>& o);
00196   
00197 private:
00198   HComponent h;
00199   Component  s,v;
00200 };
00201 
00202 
00203 
00205 template<class Component>
00206 ostream& operator<<(ostream& s, const HSVPixel<Component>& o)
00207   {  return cout << "(" << o.hue() << "," << o.saturation() << "," << o.value() << ")";  }
00208 
00209 
00210 
00216 template<class Component>
00217 template<class OComponent, class OHComponent>
00218 RGBPixel<Component>::RGBPixel(const HSVPixel<OComponent,OHComponent>& other) : Pixel(other)
00219 {
00220   int    j;
00221   double rd, gd, bd;
00222   double f, p, q, T;
00223   double hue;
00224   
00225   double h=other.hue();
00226   double s=other.saturation();
00227   double v=other.value();
00228   
00229   /* convert HSV back to RGB */
00230   if (s==0.0) { rd = v;  gd = v;  bd = v; }
00231   else {
00232     /* hue ranges [0,6) */
00233     hue = h * 6.0;
00234     
00235     j = (int) floor(hue);
00236     if (j<0) j=0;          /* either h or floor seem to go neg on some sys */
00237     f = hue - j;
00238     p = v * (1-s);
00239     q = v * (1 - (s*f));
00240     T = v * (1 - (s*(1 - f)));
00241     
00242     switch (j) {
00243     case 0:  rd = v;  gd = T;  bd = p;  break;
00244     case 1:  rd = q;  gd = v;  bd = p;  break;
00245     case 2:  rd = p;  gd = v;  bd = T;  break;
00246     case 3:  rd = p;  gd = q;  bd = v;  break;
00247     case 4:  rd = T;  gd = p;  bd = v;  break;
00248     case 5:  rd = v;  gd = p;  bd = q;  break;
00249     default: rd = v;  gd = T;  bd = p;  break;  /* never happen */
00250     }
00251   }
00252   
00253   r = Component(Bounded::LargeInt(floor( rd*r.Max + 0.5 )));
00254   g = Component(Bounded::LargeInt(floor( gd*g.Max + 0.5 )));
00255   b = Component(Bounded::LargeInt(floor( bd*b.Max + 0.5 )));
00256 }
00257 
00258 
00259 
00266 template<class Component, class HComponent>
00267 template<class OComponent>
00268 HSVPixel<Component,HComponent>::HSVPixel(const RGBPixel<OComponent>& other) : Pixel(other)
00269 {
00270   double r = other.red();
00271   double g = other.green();
00272   double b = other.blue();
00273 
00274   double hh;
00275   
00276   double maxval = std::max(std::max(r,g),b);
00277   double minval = std::min(std::min(r,g),b);
00278 
00279   /* Value */
00280   v = maxval;
00281 
00282   /* Saturation */
00283   s = (maxval == 0.0) ? 0.0 : ((maxval-minval)/maxval);
00284   
00285   /* Hue */
00286   if (s.mag() == 0.0)
00287     hh = 0;
00288   else {
00289     double delt = maxval - minval;
00290     
00291     if (r == maxval)
00292       hh =       (g - b)/delt; /* Between yellow and magenta */
00293     
00294     else if (g == maxval)
00295       hh = 2.0 + (b - r)/delt; /* Between cyan and yellow    */
00296     
00297     else if (b  == maxval)
00298       hh = 4.0 + (r - g)/delt; /* Between magenta and cyan   */
00299     
00300     /* Convert to degrees (disabled) */
00301     /* *h *= 60; if (*h < 0.0) *h += 360; */
00302     
00303     /* Scale to Max */
00304     hh *= (60.0/360.0); if (hh < 0.0) hh = hh+h.Max;
00305     h = hh;
00306   }
00307 
00308 }
00309 
00310 
00311 
00319 template<class HSVPixelType=HSVPixel<> >
00320 class PixelAverage {
00321 private:
00322   double valtot, colorx, colory, count;
00323 
00324 public:
00325   PixelAverage() : valtot(0), colorx(0), colory(0), count(0)  { }
00326 
00328   void operator+=(HSVPixelType p) {
00329     const double angle = 2*M_PI*p.hue();
00330     const double mag   = p.saturation();
00331     colorx += mag * cos(angle);
00332     colory += mag * sin(angle);
00333     valtot += p.value();
00334     count++;
00335   }
00336   
00338   HSVPixelType operator() () const {
00339     const Bounded::Magnitude hue = atan2(colory,colorx)/2/M_PI;
00340     const Bounded::Magnitude sat = sqrt(colorx*colorx+colory*colory)/count;
00341     const Bounded::Magnitude val = valtot/count;
00342     return HSVPixel<>(hue,sat,val);
00343   }
00344 };
00345 
00346     
00347 
00357 template<class HSVPixelType>  
00358 RGBPixel<>  contrasting_color( HSVPixelType prevailing_color) {
00359   const Bounded::Magnitude  val = prevailing_color.value();
00360   if      (val >= 0.75) return RGBPixel<>(0,0,0); /* bright background */
00361   else if (val <  0.25) return RGBPixel<>(1,1,1); /* dark background   */
00362   else                  return RGBPixel<>(0,0,1); /* medium background */
00363 }
00364 
00365   
00366 } /* namespace Plot */
00367 #endif /* __PIXEL_H__ */

Generated at Mon Aug 21 00:30:54 2000 for RF-LISSOM by doxygen1.2.1 written by Dimitri van Heesch, © 1997-2000