www.pudn.com > firev0.01.rar > colorpixel.hpp


/*
This file is part of the FIRE -- Flexible Image Retrieval System

FIRE is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

FIRE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with FIRE; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifndef __rgbpixel_h
#define __rgbpixel_h

#include 
#include 

using namespace std;

namespace img {

 
/** Class to store a ColorPixel.  
 *
 * Very basic class which stores three values which are interpreted as
 * red, green and blue value respectively
 */
template 
class ColorPixel {
public:
  /// default constructor.
  ColorPixel() {};
  /// standard constructor 1, all three values get c.
  ColorPixel(T c) {r_=c, g_=c, b_=c;};
  /// standard constructor 2, every value gets it's own value.
  ColorPixel(T r, T g, T b) { r_=r; g_=g; b_=b;};
  /// copy constructor.
  ColorPixel(const ColorPixel &p) {r_=p.r();g_=p.g();b_=p.b();};

  /// give the HSV representation of this color
  // stolen from http://www.cs.rit.edu/~ncs/color/t_convert.html
  ColorPixel hsvPixel() const {
    double h,s,v;
    double min, max, delta;
      
    min=r_;
    if(g_max) max=g_;
    if(b_>max) max=b_;
    
    v = max;				// v=max(r,g,b)
      
    delta = max - min;

    if( max != 0 )
      s = delta / max;		// s
    else {
      // r = g = b = 0		// s = 0, h is undefined
      s = 0;
      h = 0;
      return ColorPixel(h,s,v);
    }

    if(delta==0) h=0;
    else {
      if( r_ == max ) {
	if(delta==0) cout << "FEHLER" << endl;
	h = ( g_ - b_ ) / delta;		// between yellow & magenta
      }
      else if( g_ == max ) {
	if(delta==0) cout << "FEHLER" << endl;
	h = 2 + ( b_ - r_ ) / delta;	// between cyan & yellow
      } 
      else {
	if(delta==0) cout << "FEHLER" << endl;
	h = 4 + ( r_ - g_ ) / delta;	// between magenta & cyan
      }
      h *= 60;				// degrees
    }
    if( h < 0 )
      h += 360;
    return ColorPixel(h,s,v);
  }
  
  ColorPixel complexPixel() const {
    ColorPixel result;
    ColorPixel tmp;
    tmp=this->hsvPixel();
    result[0]=tmp[1]*cos(double(tmp[0]));
    result[1]=tmp[1]*sin(double(tmp[0]));
    result[2]=tmp[2];
    return result;
  }
  
  ColorPixel hsvPixel(ColorPixel in) {
    int i;
    T f, p, q, t;
    
    //interpret the in pixel as hsv pixel
    T h=in.r();
    T s=in.g();
    T v=in.b();
    
    if( s == 0 ) {
      // achromatic (grey)
      r_ = g_ = b_ = v;
      return;
    }
    
    h /= 60;			// sector 0 to 5
    i = floor( h );
    f = h - i;			// factorial part of h
    p = v * ( 1 - s );
    q = v * ( 1 - s * f );
    t = v * ( 1 - s * ( 1 - f ) );
    
    switch( i ) {
    case 0:
      r_ = v;
      g_ = t;
      b_ = p;
      break;
    case 1:
      r_ = q;
      g_ = v;
      b_ = p;
      break;
    case 2:
      r_ = p;
      g_ = v;
      b_ = t;
      break;
    case 3:
      r_ = p;
      g_ = q;
      b_ = v;
      break;
    case 4:
      r_ = t;
      g_ = p;
      b_ = v;
      break;
    default:		// case 5:
      r_ = v;
      g_ = p;
      b_ = q;
      break;
    }
  }
  
  ///get the red value, const version.
  inline const T r() const {return r_;};
  ///get the red value.
  inline T& r(){return r_;};

  ///get the green value, const version.
  inline const T g() const {return g_;}; 
  ///get the green value.
  inline T& g() {return g_;};

  ///get the blue value, const version.
  inline const T b() const {return b_;};
  ///get the blue value.
  inline T& b() {return b_;};
      
  ///get the values by index, const version
  /** get the values by index, const version, where
   * -# 0 is red
   * -# 1 is green
   * -# 2 is blue
   * take care, there is no checking done 
   */
  inline const T operator[](const int i) const {
    switch(i) {
    case 0: return r_; break;
    case 1: return g_; break;
    case 2: return b_; break;
    default: return -1; 
    }
  }
      
  ///get the values by index.
  /** get the values by index, where
   * -# 0 is red
   * -# 1 is green
   * -# 2 is blue
   * take care, there is no checking done 
   */
  inline T & operator[](const int i) {
    switch(i) {
    case 0: return r_; break;
    case 1: return g_; break;
    case 2: return b_; break;
    default: return r_;
    }
  }
                  
  ///assigment operator, "copy" the rhs.
  inline const ColorPixel& operator=(const ColorPixel &rhs) {
    this->r_=rhs.r();
    this->g_=rhs.g();
    this->b_=rhs.b();
    return *this;
  }
                    
  ///assignement operator, all values get the value of rhs.
  inline const T & operator=(const T &rhs) {
    this->r_=rhs; 
    this->g_=rhs;
    this->b_=rhs;
    return rhs;
  }
      
  ///unary addition, add the values from rhs.
  inline const ColorPixel& operator+=(const ColorPixel &rhs) {
    this->r_+=rhs.r();
    this->g_+=rhs.g();
    this->b_+=rhs.b();
    return *this;
  }

  ///unary division, divide the values by the values from the rhs
  inline const ColorPixel& operator/=(const ColorPixel &rhs) {
    this->r_/=rhs.r();
    this->g_/=rhs.g();
    this->b_/=rhs.b();
    return *this;
  }

  ///unary division, divide the values by the rhs
  inline const ColorPixel& operator/=(T &rhs) {
    this->r_/=rhs;
    this->g_/=rhs;
    this->b_/=rhs;
    return *this;
  }

    
  ///elementwise multiplication.
  inline const ColorPixel operator*(const ColorPixel &rhs) const {
    ColorPixel temp;
    temp.r()=this->r()*rhs.r();
    temp.g()=this->g()*rhs.g();
    temp.b()=this->b()*rhs.b();
    return temp;
  }

private:
  T r_,g_,b_;
};


  /**
   * Print out an ColorPixel to a given stream.
   */
  template
  inline ostream& operator<< (ostream& os, const ColorPixel &src) {
    os << "(" << setw(4) << double(src.r()) << ", "<< setw(4)<