core/vil/vil_rgb.h
Go to the documentation of this file.
00001 // This is core/vil/vil_rgb.h
00002 #ifndef vil_rgb_h_
00003 #define vil_rgb_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Pixel type for 24 bit images
00010 //
00011 //  Currently also includes the following `utilities':
00012 //   - conversion to ubyte (luminance of vil_rgb: weights (0.299,0.587,0.114)).
00013 //   - min and max of vil_rgbcell values, useful for morphological operations.
00014 //   - arithmetic operations
00015 //
00016 // \author Peter Vanroose, K.U.Leuven, ESAT/VISICS
00017 // \date   15 nov. 1997
00018 //
00019 //\verbatim
00020 //  Modifications:
00021 //    250198 AWF Templated.
00022 //    250198 AWF Modified to make POD struct until gcc inlines when debugging.
00023 //    160298 PCP Removed underscore from public members.
00024 //    290798 AWF Member templates for fancy compilers
00025 //    220598 PVr moved instantiations files to Templates subdirectory.
00026 //    050598 PVr added several operators ( + += - -= (T) ).
00027 //    140898 David Capel added clamping functions to ensure 0-255 range on bytes and vil_rgb<byte>
00028 //    090600 David Capel made clamping functions inline and removed all that partial specialization nonsense from the .txx file.
00029 //   Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
00030 //\endverbatim
00031 
00032 #include <vcl_iostream.h>
00033 
00034 #ifdef VCL_SUNPRO_CC
00035 # define InLine inline
00036 #else
00037 # define InLine
00038 #endif
00039 
00040 //: This is the appropriate pixel type for 24-bit colour images.
00041 //
00042 //    Currently also includes the following `utilities':
00043 //    -  conversion to ubyte (luminance of vil_rgb: weights (0.299,0.587,0.114)).
00044 //    -  min and max of vil_rgbcell values, useful for morphological operations.
00045 //    -  arithmetic operations
00046 template <class T>
00047 struct vil_rgb
00048 {
00049   typedef T value_type;
00050 
00051   inline vil_rgb() { }
00052 
00053   //:Create grey (v,v,v) vil_rgb cell from value v.
00054   // This provides a conversion from T to vil_rgb<T>
00055 
00056   inline vil_rgb(T v):
00057     r(v), g(v), b(v) {}
00058 
00059   //: Construct a vil_rgb value.
00060   inline vil_rgb(T red, T green, T blue):
00061     r(red), g(green), b(blue) {}
00062 
00063   // The rgb values
00064   T r, g, b;
00065   inline T R() const { return r; }
00066   inline T G() const { return g; }
00067   inline T B() const { return b; }
00068 
00069   //:Convert vil_rgb to gray using standard (.299, .587, .114) weighting.
00070   inline T grey() const { return T(r*0.299+0.587*g+0.114*b); }
00071 
00072 #if 0 // deprecated -- use .grey() instead
00073   inline operator T() const { return T(0.5+r*0.299+0.587*g+0.114*b); }
00074 #endif
00075 
00076   //: equality
00077   inline bool operator== (vil_rgb<T> const& o) const { return r==o.r && g==o.g && b==o.b; }
00078 
00079   // operators
00080   inline vil_rgb<T>  operator+  (vil_rgb<T> const& A) const { return vil_rgb<T>(r+A.r,g+A.g,b+A.b); }
00081   inline vil_rgb<T>  operator-  (vil_rgb<T> const& A) const { return vil_rgb<T>(r-A.r,g-A.g,b-A.b); }
00082   inline vil_rgb<T>  operator/  (vil_rgb<T> const& A) const { return vil_rgb<T>(r/A.r,g/A.g,b/A.b);}
00083   inline vil_rgb<T>& operator+= (vil_rgb<T> const& A) { r+=A.r,g+=A.g,b+=A.b; return *this; }
00084   inline vil_rgb<T>& operator-= (vil_rgb<T> const& A) { r-=A.r,g-=A.g,b-=A.b; return *this; }
00085   inline vil_rgb<T>  operator*  (T A) const { return vil_rgb<T>(r*A,g*A,b*A); }
00086   inline vil_rgb<T>  operator/  (T A) const { return vil_rgb<T>(r/A,g/A,b/A); }
00087   inline vil_rgb<T>& operator*= (T A) { r*=A,g*=A,b*=A; return *this; }
00088   inline vil_rgb<T>& operator/= (T A) { r/=A,g/=A,b/=A; return *this; }
00089 
00090 #define vil_rgb_call(m) \
00091 m(unsigned char) \
00092 m(int) \
00093 m(long) \
00094 m(double)
00095 
00096 // VC50 bombs with INTERNAL COMPILER ERROR on template member functions.
00097 #if VCL_HAS_MEMBER_TEMPLATES
00098   template <class S> inline
00099   vil_rgb(vil_rgb<S> const& that):
00100     r(T(that.r)),
00101     g(T(that.g)),
00102     b(T(that.b)) { }
00103   template <class S> inline
00104   vil_rgb<T>& operator=(vil_rgb<S> const& that) {
00105     r=T(that.r);
00106     g=T(that.g);
00107     b=T(that.b);
00108     return *this;
00109   }
00110 #else
00111   // For dumb compilers, just special-case the commonly used types.
00112 # define macro(S) \
00113   inline vil_rgb(vil_rgb<S > const& that) : \
00114   r(T(that.r)), \
00115   g(T(that.g)), \
00116   b(T(that.b)) {}
00117 vil_rgb_call(macro)
00118 # undef macro
00119 
00120 # define macro(S) \
00121   InLine vil_rgb<T>& operator=(vil_rgb<S > const& that);
00122 vil_rgb_call(macro)
00123 # undef macro
00124 #endif
00125 };
00126 
00127 // see above
00128 #if VCL_HAS_MEMBER_TEMPLATES
00129 #else
00130 # define macro(S) \
00131 template <class T> inline \
00132 vil_rgb<T>& vil_rgb<T>::operator=(vil_rgb<S > const& that) { \
00133   r=T(that.r); \
00134   g=T(that.g); \
00135   b=T(that.b); \
00136   return *this; \
00137 }
00138 
00139 vil_rgb_call(macro)
00140 # undef macro
00141 #endif
00142 
00143 #undef vil_rgb_call
00144 
00145 template <class T>
00146 inline
00147 vcl_ostream& operator<<(vcl_ostream& s, vil_rgb<T> const& rgb)
00148 {
00149   return s << '[' << rgb.r << ' ' << rgb.g << ' ' << rgb.b << ']';
00150 }
00151 
00152 VCL_DEFINE_SPECIALIZATION
00153 vcl_ostream& operator<<(vcl_ostream& s, vil_rgb<unsigned char> const& rgb);
00154 
00155 
00156 // ** Arithmetic operators
00157 
00158 template <class T>
00159 inline
00160 bool operator!= (vil_rgb<T> const& a, vil_rgb<T> const& b)
00161 {
00162   return !(a==b);
00163 }
00164 
00165 template <class T>
00166 inline
00167 vil_rgb<T> average(vil_rgb<T> const& a, vil_rgb<T> const& b)
00168 {
00169   return vil_rgb<T>((a.r + b.r)/2, (a.g + b.g)/2, (a.b + b.b)/2);
00170 }
00171 
00172 template <class T>
00173 inline
00174 vil_rgb<T> operator+(vil_rgb<T> const& a, vil_rgb<T> const& b)
00175 {
00176   return vil_rgb<T>(a.r + b.r, a.g + b.g, a.b + b.b);
00177 }
00178 
00179 template <class T>
00180 inline
00181 vil_rgb<T> operator*(vil_rgb<T> const& a, vil_rgb<T> const& b)
00182 {
00183   return vil_rgb<T>(a.r * b.r, a.g * b.g, a.b * b.b);
00184 }
00185 
00186 template <class T>
00187 inline
00188 vil_rgb<double> operator*(double b, vil_rgb<T> const& a)
00189 {
00190   return vil_rgb<double>(a.r * b, a.g * b, a.b * b);
00191 }
00192 
00193 template <class T>
00194 inline
00195 vil_rgb<double> operator*(vil_rgb<T> const& a, double b)
00196 {
00197   return vil_rgb<double>(a.r * b, a.g * b, a.b * b);
00198 }
00199 
00200 template <class T>
00201 inline
00202 vil_rgb<double> operator/(vil_rgb<T> const& a, double b)
00203 {
00204   return vil_rgb<double>(a.r / b, a.g / b, a.b / b);
00205 }
00206 
00207 #define VIL_RGB_INSTANTIATE(T) \
00208 extern "you must include vil/vil_rgb.txx first."
00209 #define VIL_RGB_INSTANTIATE_LS(T) \
00210 extern "you must include vil/vil_rgb.txx first."
00211 
00212 #endif // vil_rgb_h_