00001
00007 #ifndef __PIXEL_H__
00008 #define __PIXEL_H__
00009
00010 #include <cmath>
00011
00012
00013 #include "../src/boundednumber.h"
00014
00016 namespace Plot {
00017
00018
00019
00020
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 00061 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
00230 if (s==0.0) { rd = v; gd = v; bd = v; }
00231 else {
00232
00233 hue = h * 6.0;
00234
00235 j = (int) floor(hue);
00236 if (j<0) j=0;
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;
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
00280 v = maxval;
00281
00282
00283 s = (maxval == 0.0) ? 0.0 : ((maxval-minval)/maxval);
00284
00285
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;
00293
00294 else if (g == maxval)
00295 hh = 2.0 + (b - r)/delt;
00296
00297 else if (b == maxval)
00298 hh = 4.0 + (r - g)/delt;
00299
00300
00301
00302
00303
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);
00361 else if (val < 0.25) return RGBPixel<>(1,1,1);
00362 else return RGBPixel<>(0,0,1);
00363 }
00364
00365
00366 }
00367 #endif