LTI-Lib latest version v1.9 - last update 24 Nov 2005
Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ltiRGBPixel.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1998, 1999, 2000, 2001
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /*----------------------------------------------------------------
00025  * project ....: LTI Digital Image/Signal Processing Library
00026  * file .......: ltiRGBPixel.h
00027  * authors ....: Pablo Alvarado
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 01.11.2002
00030  * revisions ..: $Id: ltiRGBPixel.h,v 1.23 2005/06/16 09:32:39 doerfler Exp $
00031  */
00032 
00033 #ifndef LTI_RGB_PIXEL_H
00034 #define LTI_RGB_PIXEL_H
00035 
00036 #include <iostream>
00037 #include "ltiIoHandler.h"
00038 #include "ltiConfig.h"
00039 #include "ltiAssert.h"
00040 #include "ltiTypes.h"
00041 
00042 /**
00043  * @file ltiRGBPixel.h
00044  *
00045  * This file contains the definitions of the basic color types used in
00046  * the LTI-Lib:
00047  *  - lti::rgbPixel
00048  *  - lti::trgbPixel
00049  */
00050 
00051 namespace lti {
00052 
00053   /**
00054    * Color pixel representation in RGB color space.
00055    *
00056    * This type ensures that a size of 32-bits.
00057    * Each channel use values between 0 and 255, and a fourth "dummy" or "alpha"
00058    * channel is used to complete the 32-bits.
00059    *
00060    * If you need to use pixel values for the RGB channels of other types
00061    * you can use lti::trgbPixel.
00062    *
00063    * @ingroup gColor
00064    */
00065   class rgbPixel {
00066   protected:
00067     /**
00068      * @union rgbPixelType
00069      * this union allows to share the memory of a 32 bit integer with the
00070      * three ubytes of RGB and a dummy byte.
00071      *
00072      * The order of the data in this union assumes little endianness
00073      */
00074     union rgbPixelType {
00075       /**
00076        * all three channels (and dummy value) together
00077        */
00078       uint32 value;
00079 
00080       /**
00081        * the three channels
00082        */
00083       struct channelsType {
00084       //  the sequence blue, green red _is_ important!
00085 
00086         /**
00087          * blue channel
00088          */
00089         ubyte blue;
00090         /**
00091          * green channel
00092          */
00093         ubyte green;
00094         /**
00095          * red channel
00096          */
00097         ubyte red;
00098         /**
00099          * dummy channel
00100          */
00101         ubyte dummy;
00102       };
00103 
00104       /**
00105        * The channel values instance
00106        */
00107       channelsType channels;
00108     };
00109 
00110     /**
00111      * The data of the pixel
00112      */
00113     rgbPixelType data;
00114 
00115   public:
00116 
00117     /**
00118      * used for the template-based interface for pixels as vectors.
00119      */
00120     typedef ubyte value_type;
00121 
00122     /**
00123      * return type of the size() member
00124      */
00125     typedef int size_type;
00126 
00127     /**
00128      * default constructor
00129      */
00130     rgbPixel() {};
00131 
00132     /**
00133      * constructor with member initialization
00134      *
00135      * Per default a new rgbPixel will be initialized with the given value.
00136      * @param val a 4 byte value to be
00137      *            assign to the three channels + dummy.
00138      *             Note that the order depends on the system endianness:
00139      *             - If you use little endian (for example: Intel Processor)
00140      *               a value of 0x00010203 means red=01,green=02 and blue=03
00141      *             - If you use big endian (for example: PowerPC Processor)
00142      *               a value of 0x00010203 means red=02,green=01 and blue=00
00143      *             Avoid the use of this constructor if you want to maintain
00144      *             platform compatibility.
00145      */
00146     rgbPixel(const uint32 val) {
00147       data.value = val;
00148     };
00149 
00150     /**
00151      * rgb constructor
00152      * @param r 8 bit value for the red component
00153      * @param g 8 bit value for the green component
00154      * @param b 8 bit value for the blue component
00155      * @param d 8 bit value for the dummy byte (default value 0)
00156      */
00157     rgbPixel(const ubyte r,const ubyte g,const ubyte b,const ubyte d=0) {
00158       data.channels.dummy = d;
00159       data.channels.red   = r;
00160       data.channels.green = g;
00161       data.channels.blue  = b;
00162     };
00163 
00164     /**
00165      * set the red, green, blue and dummy values for the pixel
00166      */
00167     inline void set(const ubyte red, const ubyte green, const ubyte blue,
00168                     const ubyte dummy) {
00169       data.channels.dummy = dummy;
00170       data.channels.red   = red;
00171       data.channels.green = green;
00172       data.channels.blue  = blue;
00173     };
00174 
00175     /**
00176      * set the red, green, blue values for the pixel
00177      */
00178     inline void set(const ubyte red, const ubyte green, const ubyte blue) {
00179       data.channels.red   = red;
00180       data.channels.green = green;
00181       data.channels.blue  = blue;
00182     };
00183 
00184     /**
00185      * sets the red component to given value
00186      */
00187     inline void setRed(const ubyte r) {data.channels.red = r;};
00188 
00189     /**
00190      * sets the green component to given value
00191      */
00192     inline void setGreen(const ubyte g) {data.channels.green = g;};
00193 
00194     /**
00195      * sets the blue component to given value
00196      */
00197     inline void setBlue(const ubyte b) {data.channels.blue = b;};
00198 
00199     /**
00200      * sets the dummy component to given value
00201      */
00202     inline void setDummy(const ubyte d) {data.channels.dummy = d;};
00203 
00204     /**
00205      * sets the value component (all components together) to given value
00206      */
00207     inline void setValue(const uint32& v) {data.value = v;};
00208 
00209     /**
00210      * Get the three color components and write them in the given arguments
00211      */
00212     inline void get(ubyte& red,ubyte& green,ubyte& blue) const {
00213       red   = data.channels.red;
00214       green = data.channels.green;
00215       blue  = data.channels.blue;
00216     };
00217 
00218     /**
00219      * Get the three color components and write them in the given arguments
00220      */
00221     inline void get(int& red,int& green,int& blue) const {
00222       red   = data.channels.red;
00223       green = data.channels.green;
00224       blue  = data.channels.blue;
00225     };
00226 
00227     /**
00228      * Get the four components and write them in the given arguments
00229      */
00230     inline void get(ubyte& red,ubyte& green,ubyte& blue,ubyte& dummy) const {
00231       red   = data.channels.red;
00232       green = data.channels.green;
00233       blue  = data.channels.blue;
00234       dummy = data.channels.dummy;
00235     };
00236 
00237     /**
00238      * Get the four components and write them in the given arguments
00239      */
00240     inline void get(int& red,int& green,int& blue,int& dummy) const {
00241       red   = data.channels.red;
00242       green = data.channels.green;
00243       blue  = data.channels.blue;
00244       dummy = data.channels.dummy;
00245     };
00246 
00247     /**
00248      * returns red component
00249      */
00250     inline const ubyte& getRed()   const {return data.channels.red;};
00251 
00252     /**
00253      * returns green component
00254      */
00255     inline const ubyte& getGreen() const {return data.channels.green;};
00256 
00257     /**
00258      * returns blue component
00259      */
00260     inline const ubyte& getBlue()  const {return data.channels.blue;};
00261 
00262     /**
00263      * returns dummy component
00264      */
00265     inline const ubyte& getDummy() const {return data.channels.dummy;};
00266 
00267     /**
00268      * returns 4 byte component with RGB value
00269      */
00270     inline const uint32& getValue() const {return data.value;};
00271 
00272     /**
00273      * returns 4 byte component with RGB value
00274      */
00275     inline uint32& getValue() {return data.value;};
00276 
00277     /**
00278      * Used to simulate vector access.
00279      * The correspondence between the elements of the vector and
00280      * the color components is at(0) for red, at(1) for green and
00281      * at(2) for blue.
00282      */
00283     inline ubyte& at(const int x) {
00284       assert(x<3 && x >= 0);
00285       return ((ubyte*)(&data.value))[2-x];
00286     }
00287 
00288     /**
00289      * Used to simulate read-only vector access.
00290      * The correspondence between the elements of the vector and
00291      * the color components still depents on the endianness of the
00292      * system, but is usually at(0) for red, at(1) for green and
00293      * at(2) for blue.
00294      */
00295     inline const ubyte& at(const int x) const {
00296       assert(x<3 && x >= 0);
00297       return ((ubyte*)(&data.value))[2-x];
00298     }
00299 
00300     /**
00301      * Used to simulate vector access.
00302      * The correspondence between the elements of the vector and
00303      * the color components is [0] for red, [1] for green and
00304      * [2] for blue.
00305      */
00306     inline ubyte& operator[](const int x) {
00307       assert(x<3 && x >= 0);
00308       return (&data.channels.red)[-x];
00309     }
00310 
00311     /**
00312      * Used to simulate read-only vector access.
00313      * The correspondence between the elements of the vector and
00314      * the color components still depents on the endianness of the
00315      * system, but is usually [0] for red, [1] for green and
00316      * [2] for blue.
00317      */
00318     inline const ubyte& operator[](const int x) const {
00319       assert(x<3 && x >= 0);
00320       return (&data.channels.red)[-x];
00321     }
00322 
00323     /**
00324      * Used to simulate the vector size
00325      */
00326     inline int size() const {
00327       return 3;
00328     }
00329 
00330     /**
00331      * copy the "other" pixel
00332      */
00333     inline rgbPixel& copy(const rgbPixel& other) {
00334       setValue(other.getValue());
00335       return (*this);
00336     };
00337     /**
00338      * alias for copy
00339      */
00340     inline rgbPixel& operator=(const rgbPixel& other) {
00341       return(copy(other));
00342     };
00343 
00344     /**
00345      * Compares this pixel with the specified other pixel. 
00346      * Two pixels are considered equal if all four (!) channels,
00347      * i.e. R, G, B, and dummy, are equal. A call to this method
00348      * is equivalent to this->getValue() == other.getValue().
00349      */
00350     inline bool isEqual(const rgbPixel& other) const {
00351       return (getValue() == other.getValue());
00352     }
00353 
00354     /**
00355      * Compares the color of this pixel with the specified
00356      * other pixel. Only the three RGB channels are considered;
00357      * the dummy value is ignored.
00358      */
00359     inline bool isEqualColor(const rgbPixel& other) const {
00360       return getRed() == other.getRed()
00361         && getGreen() == other.getGreen() 
00362         && getBlue() == other.getBlue();
00363     }
00364 
00365     /**
00366      * Alias for isEqual(). Please note the difference between
00367      * isEqual() and isEqualColor()!
00368      */
00369     inline bool operator==(const rgbPixel& other) const {
00370       return (isEqual(other));
00371     };
00372 
00373     /**
00374      * alias for !compare()
00375      */
00376     inline bool operator!=(const rgbPixel& other) const {
00377       return (!isEqual(other));
00378     };
00379 
00380     /**
00381      * An rgbPixel is said to be "smaller" than another one, if
00382      * getValue() < other.getValue()
00383      */
00384     inline bool operator<(const rgbPixel& other) const {
00385       return (getValue() < other.getValue());
00386     }
00387 
00388     /**
00389      * An rgbPixel is said to be "bigger" than another one, if
00390      * getValue() > other.getValue()
00391      */
00392     inline bool operator>(const rgbPixel& other) const {
00393       return (getValue() > other.getValue());
00394     }
00395 
00396     /**
00397      * add this pixel with another one
00398      */
00399     inline rgbPixel& add(const rgbPixel& other) {
00400 
00401       setRed(getRed()+other.getRed());
00402       setGreen(getGreen()+other.getGreen());
00403       setBlue(getBlue()+other.getBlue());
00404 
00405       return (*this);
00406     }
00407 
00408     /**
00409      * alias for add
00410      */
00411     inline rgbPixel& operator+=(const rgbPixel& other) {
00412       return add(other);
00413     }
00414 
00415     /**
00416      * add this pixel with the otherone without altering anything...
00417      */
00418     inline rgbPixel operator+(const rgbPixel& other) const {
00419       rgbPixel tmp(*this);
00420       tmp.add(other);
00421       return tmp;
00422     }
00423 
00424     /**
00425      * subtract 'other' from this pixel
00426      */
00427     inline rgbPixel& subtract(const rgbPixel& other) {
00428 
00429       setRed(getRed()-other.getRed());
00430       setGreen(getGreen()-other.getGreen());
00431       setBlue(getBlue()-other.getBlue());
00432 
00433       return (*this);
00434     }
00435 
00436     /**
00437      * alias for subtract
00438      */
00439     inline rgbPixel& operator-=(const rgbPixel& other) {
00440       return subtract(other);
00441     }
00442 
00443     /**
00444      * subtract 'other' from this pixel without altering anything...
00445      */
00446     inline rgbPixel operator-(const rgbPixel& other) const {
00447       rgbPixel tmp(*this);
00448       tmp.subtract(other);
00449       return tmp;
00450     }
00451 
00452     /**
00453      * multiply this pixel with another one
00454      * the pixel multiplication multiplies elementwise the elements of
00455      * the pixel!
00456      */
00457     inline rgbPixel& multiply(const rgbPixel& other) {
00458 
00459       setRed(getRed()*other.getRed());
00460       setGreen(getGreen()*other.getGreen());
00461       setBlue(getBlue()*other.getBlue());
00462 
00463       return (*this);
00464     }
00465 
00466     /**
00467      * alias for multiply()
00468      */
00469     inline rgbPixel& operator*=(const rgbPixel& other) {
00470       return multiply(other);
00471     }
00472 
00473     /**
00474      * multiply this pixel with another one without altering anything...
00475      */
00476     inline rgbPixel operator*(const rgbPixel& other) const {
00477       rgbPixel tmp(*this);
00478       tmp.multiply(other);
00479       return tmp;
00480     }
00481 
00482     /**
00483      * multiply this pixel with an integer
00484      */
00485     inline rgbPixel& multiply(const int& other) {
00486 
00487       setRed(getRed()*other);
00488       setGreen(getGreen()*other);
00489       setBlue(getBlue()*other);
00490 
00491       return (*this);
00492     }
00493 
00494     /**
00495      * multiply this pixel with a float.
00496      */
00497     inline rgbPixel& multiply(const float& other) {
00498 
00499       setRed(static_cast<ubyte>(other*getRed()));
00500       setGreen(static_cast<ubyte>(other*getGreen()));
00501       setBlue(static_cast<ubyte>(other*getBlue()));
00502 
00503       return (*this);
00504     }
00505 
00506     /**
00507      * multiply this pixel with a float.
00508      */
00509     inline rgbPixel& multiply(const double& other) {
00510 
00511       setRed(static_cast<ubyte>(other*getRed()));
00512       setGreen(static_cast<ubyte>(other*getGreen()));
00513       setBlue(static_cast<ubyte>(other*getBlue()));
00514 
00515       return (*this);
00516     }
00517 
00518     /**
00519      * alias for multiply
00520      */
00521     inline rgbPixel& operator*=(const int& other) {
00522       return multiply(other);
00523     }
00524 
00525     /**
00526      * alias for multiply
00527      */
00528     inline rgbPixel& operator*=(const float& other) {
00529       return multiply(other);
00530     }
00531 
00532     /**
00533      * alias for multiply
00534      */
00535     inline rgbPixel& operator*=(const double& other) {
00536       return multiply(other);
00537     }
00538 
00539     /**
00540      * multiply this pixel with another one without altering anything...
00541      */
00542     inline rgbPixel operator*(const int& other) const {
00543       rgbPixel tmp(*this);
00544       tmp.multiply(other);
00545       return tmp;
00546     }
00547 
00548     /**
00549      * multiply this pixel with a float an return a new one.
00550      */
00551     inline rgbPixel operator*(const float& other) const {
00552       rgbPixel tmp(*this);
00553       tmp.multiply(other);
00554       return tmp;
00555     }
00556 
00557     /**
00558      * multiply this pixel with a float an return a new one.
00559      */
00560     inline rgbPixel operator*(const double& other) const {
00561       rgbPixel tmp(*this);
00562       tmp.multiply(other);
00563       return tmp;
00564     }
00565 
00566 
00567     /**
00568      * divide this pixel with another one
00569      * the pixel division divides elementwise the elements of
00570      * the pixel!
00571      */
00572     inline rgbPixel& divide(const rgbPixel& other) {
00573 
00574       setRed(getRed()/other.getRed());
00575       setGreen(getGreen()/other.getGreen());
00576       setBlue(getBlue()/other.getBlue());
00577 
00578       return (*this);
00579     }
00580 
00581     /**
00582      * alias for divide()
00583      */
00584     inline rgbPixel& operator/=(const rgbPixel& other) {
00585       return divide(other);
00586     }
00587 
00588     /**
00589      * divide this pixel with another one without altering anything...
00590      */
00591     inline rgbPixel operator/(const rgbPixel& other) const {
00592       rgbPixel tmp(*this);
00593       tmp.divide(other);
00594       return tmp;
00595     }
00596 
00597     /**
00598      * divide this pixel with an integer
00599      */
00600     inline rgbPixel& divide(const int& other) {
00601 
00602       setRed(getRed()/other);
00603       setGreen(getGreen()/other);
00604       setBlue(getBlue()/other);
00605 
00606       return (*this);
00607     }
00608 
00609     /**
00610      * alias for divide
00611      */
00612     inline rgbPixel& operator/=(const int& other) {
00613       return divide(other);
00614     }
00615 
00616     /**
00617      * divide this pixel with another one without altering anything...
00618      */
00619     inline rgbPixel operator/(const int& other) const {
00620       rgbPixel tmp(*this);
00621       tmp.divide(other);
00622       return tmp;
00623     }
00624 
00625    /**
00626     * obtain the square of the magnitud of this pixel
00627     * \f$red^2+green^2+blue^2 \f$.
00628     */
00629     inline int absSqr() const {
00630       return (int(getRed()  )*int(getRed()  )+
00631               int(getGreen())*int(getGreen())+
00632               int(getBlue() )*int(getBlue() ));
00633     }
00634 
00635    /**
00636     * get the scalar product of this pixel with another one, considering
00637     * them as a 3D vector.  The dot product will be the sum of the 
00638     * red*other.red + green*other.green + blue*other.blue
00639     */
00640     inline int dot(const rgbPixel& other) const {
00641       return (int(getRed()  )*int(other.getRed()  )+
00642               int(getGreen())*int(other.getGreen())+
00643               int(getBlue() )*int(other.getBlue() ));
00644     }
00645 
00646     /**
00647      * returns the square of the distance of this pixel to the other
00648      * one defined as
00649      * \f$(red-other.red)^2+(green-other.green)^2+(blue-other.blue)^2\f$.
00650      */
00651     inline int distanceSqr(const rgbPixel& other) const {
00652       const int 
00653         r(static_cast<int>(other.getRed())-
00654           static_cast<int>(data.channels.red)),
00655         g(static_cast<int>(other.getGreen())-
00656           static_cast<int>(data.channels.green)),
00657         b(static_cast<int>(other.getBlue())-
00658           static_cast<int>(data.channels.blue));
00659       return (r*r+g*g+b*b);
00660     }
00661 
00662   };
00663 
00664   /**
00665    * @name Constants for the primary and secondary colors, as well as
00666    * black and white.
00667    */
00668   //@{
00669   /**
00670    * constant for the color black.
00671    */
00672   const rgbPixel Black(0,0,0,0);
00673 
00674   /**
00675    * constant for the color read.
00676    */
00677   const rgbPixel Red(255,0,0,0);
00678 
00679   /**
00680    * constant for the color green.
00681    */
00682   const rgbPixel Green(0,255,0,0);
00683 
00684   /**
00685    * constant for the color blue.
00686    */
00687   const rgbPixel Blue(0,0,255,0);
00688 
00689   /**
00690    * constant for the color yellow.
00691    */
00692   const rgbPixel Yellow(255,255,0,0);
00693 
00694   /**
00695    * constant for the color magenta.
00696    */
00697   const rgbPixel Magenta(255,0,255,0);
00698 
00699   /**
00700    * constant for the color cyan.
00701    */
00702   const rgbPixel Cyan(0,255,255,0);
00703 
00704   /**
00705    * constant for the color white.
00706    */
00707   const rgbPixel White(255,255,255,0);
00708   //@}
00709 
00710   /**
00711    * read the vector from the given ioHandler.  The complete flag indicates
00712    * if the enclosing begin and end should be also be readed
00713    *
00714    * @ingroup gStorable
00715    */
00716   inline bool read(ioHandler& handler,rgbPixel& p,const bool complete=true) {
00717     int tmp;
00718     bool b = true;
00719 
00720     // the begin and end tokens are mandatory here! ignore the complete flag...
00721     handler.readBegin();
00722 
00723     b = b && handler.read(tmp);
00724     p.setRed(ubyte(tmp));
00725 
00726     b = b && handler.readDataSeparator();
00727 
00728     b = b && handler.read(tmp);
00729     p.setGreen(ubyte(tmp));
00730 
00731     b = b && handler.readDataSeparator();
00732 
00733     b = b && handler.read(tmp);
00734     p.setBlue(ubyte(tmp));
00735 
00736     if (!handler.tryEnd()) {
00737       // the new rgbPixel writes also the dummy value.  To allow
00738       // old stuff to be readed, the dummy value is optionally readed
00739       b = b && handler.readDataSeparator();
00740 
00741       b = b && handler.read(tmp);
00742       p.setDummy(ubyte(tmp));
00743 
00744       // the begin and end tokens are mandatory here! ignore the
00745       // complete flag...
00746       b = b && handler.readEnd();
00747     } else {
00748       p.setDummy(0);
00749     }
00750 
00751     return b;
00752   };
00753 
00754   /**
00755    * write the vector in the given ioHandler.  The complete flag indicates
00756    * if the enclosing begin and end should be also be written or not
00757    *
00758    * @ingroup gStorable
00759    */
00760   inline bool write(ioHandler& handler,const rgbPixel& p,
00761                     const bool complete=true) {
00762     bool b = true;
00763 
00764     // the begin token is mandatory here, so ignore the complete flag
00765     b = b && handler.writeBegin();
00766 
00767     b = b && handler.write(int(p.getRed()));
00768     b = b && handler.writeDataSeparator();
00769     b = b && handler.write(int(p.getGreen()));
00770     b = b && handler.writeDataSeparator();
00771     b = b && handler.write(int(p.getBlue()));
00772     b = b && handler.writeDataSeparator();
00773     b = b && handler.write(int(p.getDummy()));
00774     b = b && handler.writeEnd();
00775 
00776     return b;
00777   };
00778 
00779   /**
00780    * Template to use RGB pixel representations of types other than
00781    * <code>ubyte</code>.
00782    *
00783    * The type <code>rgbPixel</code> optimize speed and memory use.
00784    * If you need RGB integer values between 0 and 255, you should use rgbPixel
00785    * instead (much more efficient!)
00786    *
00787    * @see lti::drgbPixel, lti::frgbPixel, lti::irgbPixel
00788    *
00789    * @ingroup gColor
00790    */
00791   template<class T>
00792   class trgbPixel {
00793   public:
00794 
00795     /**
00796      * used for the template-based interface for pixels as vectors.
00797      */
00798     typedef T value_type;
00799 
00800     /**
00801      * return type of the size() member
00802      */
00803     typedef int size_type;
00804 
00805     /**
00806      * default constructor
00807      */
00808     trgbPixel()
00809       : red(T(0)),green(T(0)),blue(T(0)) {
00810     };
00811 
00812     /**
00813      * gray value constructor
00814      */
00815     explicit trgbPixel(const T g)
00816       : red(g),green(g),blue(g) {
00817     };
00818 
00819     /**
00820      * default constructor
00821      */
00822     trgbPixel(const T r,
00823               const T g,
00824               const T b)
00825       : red(r),green(g),blue(b) {};
00826 
00827     /**
00828      * copy constructor
00829      */
00830     trgbPixel(const trgbPixel<T>& p)
00831       : red(p.red),green(p.green),blue(p.blue) {};
00832 
00833     /**
00834      * copy constructor
00835      */
00836     trgbPixel(const rgbPixel& p)
00837       : red(p.getRed()),green(p.getGreen()),blue(p.getBlue()) {
00838     };
00839 
00840     /**
00841      * red channel
00842      */
00843     T red;
00844 
00845     /**
00846      * green channel
00847      */
00848     T green;
00849 
00850     /**
00851      * blue channel
00852      */
00853     T blue;
00854 
00855     /**
00856      * Get the three color components and write them in the given arguments
00857      */
00858     inline void get(T& r,T& g,T& b) const {
00859       r = red;
00860       g = green;
00861       b = blue;
00862     };
00863 
00864     /**
00865      * returns red value
00866      */
00867     inline const T& getRed() const {return red;};
00868 
00869     /**
00870      * returns green value
00871      */
00872     inline const T& getGreen() const {return green;};
00873 
00874     /**
00875      * returns blue value
00876      */
00877     inline const T& getBlue() const {return blue;};
00878 
00879     /**
00880      * set the red, green, blue values for the pixel
00881      */
00882     inline void set(const T r, const T g, const T b) {
00883       red   = r;
00884       green = g;
00885       blue  = b;
00886     };
00887 
00888     /**
00889      * sets red value
00890      */
00891     inline void setRed(const T r)   {red   = r;};
00892 
00893     /**
00894      * sets green value
00895      */
00896     inline void setGreen(const T g) {green = g;};
00897 
00898     /**
00899      * sets blue value
00900      */
00901     inline void setBlue(const T b)  {blue  = b;};
00902 
00903 
00904     /**
00905      * Used to simulate vector access.  It is slower than the normal
00906      * access to the elements with getRed() or setRed() similar methods.
00907      *
00908      * The correspondence between the elements of the vector and
00909      * the color components will be at(0) for red, at(1) for green and
00910      * at(2) for blue.
00911      */
00912     inline T& at(const int x) {
00913       assert(x<4);
00914       switch (x) {
00915         case 0:
00916           return red;
00917         case 1:
00918           return green;
00919         case 2:
00920           return blue;
00921         default:
00922           assert(false);
00923       }
00924 
00925       return red; // we need to return something to keep the compiler quiet!
00926     }
00927 
00928     /**
00929      * Used to simulate read-only vector access.  It is slower than the normal
00930      * access to the elements with getRed() or similar methods.
00931      *
00932      *
00933      * The correspondence between the elements of the vector and
00934      * the color components will be at(0) for red, at(1) for green and
00935      * at(2) for blue.
00936      */
00937     inline const T& at(const int x) const {
00938       assert(x<4);
00939       switch (x) {
00940         case 0:
00941           return red;
00942         case 1:
00943           return green;
00944         case 2:
00945           return blue;
00946         default:
00947           assert(false);
00948       }
00949 
00950       return red; // we need to return something to keep the compiler quiet!
00951     }
00952 
00953     /**
00954      * Used to simulate vector access.  It is slower than the normal
00955      * access to the elements with getRed() or setRed() similar methods.
00956      *
00957      * The correspondence between the elements of the vector and
00958      * the color components will be [0] for red, [1] for green and
00959      * [2] for blue.
00960      */
00961     inline T& operator[](const int x) {
00962       assert(x<4);
00963       switch (x) {
00964         case 0:
00965           return red;
00966         case 1:
00967           return green;
00968         case 2:
00969           return blue;
00970         default:
00971           assert(false);
00972       }
00973 
00974       return red; // we need to return something to keep the compiler quiet!
00975     }
00976 
00977     /**
00978      * Used to simulate read-only vector access.  It is slower than the normal
00979      * access to the elements with getRed() or similar methods.
00980      *
00981      * The correspondence between the elements of the vector and
00982      * the color components will be [0] for red, [1] for green and
00983      * [2] for blue.
00984      */
00985     inline const T& operator[](const int x) const {
00986       assert(x<4);
00987       switch (x) {
00988         case 0:
00989           return red;
00990         case 1:
00991           return green;
00992         case 2:
00993           return blue;
00994         default:
00995           assert(false);
00996       }
00997 
00998       return red; // we need to return something to keep the compiler quiet!
00999     }
01000 
01001 
01002 
01003     /**
01004      * Used to simulate the vector size
01005      */
01006     inline int size() const {
01007       return 3;
01008     }
01009 
01010     /**
01011      * copy member
01012      */
01013     trgbPixel<T>& copy(const trgbPixel<T>& other) {
01014       red   = other.red;
01015       green = other.green;
01016       blue  = other.blue;
01017       return (*this);
01018     };
01019 
01020     /**
01021      * copy member
01022      */
01023     trgbPixel<T>& copy(const rgbPixel& other) {
01024       red   = T(other.getRed());
01025       green = T(other.getGreen());
01026       blue  = T(other.getBlue());
01027       return (*this);
01028     }
01029 
01030     /**
01031      * alias for copy member
01032      */
01033     trgbPixel<T>& operator=(const trgbPixel<T>& other) {
01034       return(copy(other));
01035     };
01036 
01037     /**
01038      * alias for copy member
01039      */
01040     trgbPixel<T>& operator=(const rgbPixel& other) {
01041       return(copy(other));
01042     };
01043 
01044     /**
01045      * convert between pixels of different types
01046      */
01047     template <class U>
01048     inline trgbPixel<T>& castFrom(const trgbPixel<U>& other) {
01049       red   = static_cast<T>(other.getRed());
01050       green = static_cast<T>(other.getGreen());
01051       blue  = static_cast<T>(other.getBlue());
01052       return (*this);
01053     }
01054 
01055     /**
01056      * compare member: returns true if this is equal to other
01057      */
01058     bool isEqual(const trgbPixel<T>& other) const {
01059       return ((red == other.red) &&
01060         (green == other.green) &&
01061         (blue == other.blue));
01062     };
01063 
01064     /**
01065      * alias for compare()
01066      */
01067     inline bool operator==(const trgbPixel<T>& other) const {
01068       return (isEqual(other));
01069     };
01070 
01071     /**
01072      * alias for !compare()
01073      */
01074     inline bool operator!=(const trgbPixel<T>& other) const {
01075       return (!isEqual(other));
01076     };
01077 
01078     /**
01079      * returns true if the intensity of this color is smaller than
01080      * the intensity of the other color
01081      */
01082     inline bool operator<(const trgbPixel<T>& other) const {
01083       return ((red+green+blue) < (other.red+other.green+other.blue));
01084     }
01085 
01086     /**
01087      * returns true if the intensity of this color is bigger than
01088      * the intensity of the other color
01089      */
01090     inline bool operator>(const trgbPixel<T>& other) const {
01091       return ((red+green+blue) > (other.red+other.green+other.blue));
01092     }
01093 
01094     /**
01095      * add two pixels
01096      */
01097     trgbPixel<T>& add(const trgbPixel<T>& other) {
01098       red += other.red;
01099       green += other.green;
01100       blue += other.blue;
01101       return (*this);
01102     };
01103 
01104     /**
01105      * Add pixels a and b leave the result here.
01106      */
01107     trgbPixel<T>& add(const trgbPixel<T>& a,
01108                       const trgbPixel<T>& b) {
01109 
01110       red   = a.red   + b.red;
01111       green = a.green + b.green;
01112       blue  = a.blue  + b.blue;
01113 
01114       return (*this);
01115     };
01116 
01117     /**
01118      * add a constant to each component of the pixel
01119      */
01120     trgbPixel<T>& add(const T val) {
01121       red += val;
01122       green += val;
01123       blue += val;
01124       return (*this);
01125     };
01126 
01127     /**
01128      * alias for add
01129      */
01130     inline trgbPixel<T>& operator+=(const trgbPixel<T>& other) {
01131       return add(other);
01132     }
01133 
01134     /**
01135      * add this pixel with the otherone without altering anything...
01136      */
01137     inline trgbPixel<T> operator+(const trgbPixel<T>& other) const {
01138       trgbPixel<T> tmp(*this);
01139       tmp.add(other);
01140       return tmp;
01141     }
01142 
01143     /**
01144      * add to this pixel the other pixel scaled by the given constant
01145      */
01146     inline trgbPixel<T> addScaled(const T b,const trgbPixel<T>& other) {
01147       red += (other.red*b);
01148       green += (other.green*b);
01149       blue += (other.blue*b);
01150       return (*this);
01151     }
01152 
01153     /**
01154      * assign to this pixel the sum of the scaled pixels with their
01155      * respective scaling factors, i.e. *this = pa*a + pb*b
01156      */
01157     inline trgbPixel<T> addScaled(const T a,const trgbPixel<T>& pixa,
01158                                   const T b,const trgbPixel<T>& pixb) {
01159       red   = (pixa.red*a) + (pixb.red*b);
01160       green = (pixa.green*a) + (pixb.green*b);
01161       blue  = (pixa.blue*a) + (pixb.blue*b);
01162       return (*this);
01163     }
01164 
01165     /**
01166      * assign to this pixel the sum of the pixel pixa and the scaled
01167      * pixel pixb (scaling factor b), i.e. *this = pa + pb*b
01168      */
01169     inline trgbPixel<T> addScaled(const trgbPixel<T>& pixa,
01170                                   const T b,const trgbPixel<T>& pixb) {
01171       red   = (pixa.red) + (pixb.red*b);
01172       green = (pixa.green) + (pixb.green*b);
01173       blue  = (pixa.blue) + (pixb.blue*b);
01174       return (*this);
01175     }
01176 
01177     /**
01178      * scale this pixel with a, and add to the result the scaled
01179      * pixel pixb (scaling factor b), i.e. *this = *this*a + pb*b
01180      */
01181     inline trgbPixel<T> addScaled(const T a,
01182                                   const T b,const trgbPixel<T>& pixb) {
01183       red   = (red*a) + (pixb.red*b);
01184       green = (green*a) + (pixb.green*b);
01185       blue  = (blue*a) + (pixb.blue*b);
01186       return (*this);
01187     }
01188 
01189     /**
01190      * Subtract the \a other pixel from the current one and leave the result
01191      * here.
01192      */
01193     trgbPixel<T>& subtract(const trgbPixel<T>& other) {
01194 
01195       red -= other.red;
01196       green -= other.green;
01197       blue -= other.blue;
01198 
01199       return (*this);
01200     };
01201 
01202     /**
01203      * Subtract pixel b from pixel a and leave the result here.
01204      */
01205     trgbPixel<T>& subtract(const trgbPixel<T>& a,
01206                            const trgbPixel<T>& b) {
01207 
01208       red   = a.red   - b.red;
01209       green = a.green - b.green;
01210       blue  = a.blue  - b.blue;
01211 
01212       return (*this);
01213     };
01214 
01215 
01216     /**
01217      * subtract the given value from each component of the pixel
01218      */
01219     trgbPixel<T>& subtract(const T val) {
01220       red -= val;
01221       green -= val;
01222       blue -= val;
01223       return (*this);
01224     };
01225 
01226     /**
01227      * alias for subtract
01228      */
01229     inline trgbPixel<T>& operator-=(const trgbPixel<T>& other) {
01230       return subtract(other);
01231     }
01232 
01233     /**
01234      * subtract 'other' from this pixel without altering anything...
01235      */
01236     inline trgbPixel<T> operator-(const trgbPixel<T>& other) const {
01237       trgbPixel tmp(*this);
01238       tmp.subtract(other);
01239       return tmp;
01240     }
01241 
01242     /**
01243      * multiply with another pixel.
01244      * The pixel multiplication is a elementwise multiplication
01245      */
01246     trgbPixel<T>& multiply(const trgbPixel<T>& other) {
01247       red   *= other.red;
01248       green *= other.green;
01249       blue  *= other.blue;
01250       return (*this);
01251     }
01252 
01253     /**
01254      * Elementwise multiplication of the elements of a and b
01255      */
01256     trgbPixel<T>& multiply(const trgbPixel<T>& a,
01257                            const trgbPixel<T>& b) {
01258 
01259       red   = a.red   * b.red;
01260       green = a.green * b.green;
01261       blue  = a.blue  * b.blue;
01262 
01263       return (*this);
01264     };
01265 
01266     /**
01267      * multiply with a constant
01268      */
01269     trgbPixel<T>& multiply(const T c) {
01270       red   *= c;
01271       green *= c;
01272       blue  *= c;
01273       return (*this);
01274     }
01275 
01276     /**
01277      * multiply the elements of the other pixel with the given value, and
01278      * leave the result here.
01279      */
01280     inline trgbPixel<T>& multiply(const trgbPixel<T>& other, const T val) {
01281       red = other.red*val;
01282       green = other.green*val;
01283       blue = other.blue*val;
01284       return (*this);
01285     }
01286 
01287     /**
01288      * alias for multiply
01289      * The pixel multiplication is a elementwise multiplication
01290      */
01291     inline trgbPixel<T>& operator*=(const trgbPixel<T>& other) {
01292       return multiply(other);
01293     }
01294 
01295     /**
01296      * multiply this pixel with another one without altering anything...
01297      */
01298     inline trgbPixel<T> operator*(const trgbPixel<T>& other) const {
01299       trgbPixel<T> tmp(*this);
01300       tmp.multiply(other);
01301       return tmp;
01302     }
01303 
01304     /**
01305      * alias for multiply
01306      */
01307     inline trgbPixel<T> operator*=(const T other) {
01308       return multiply(other);
01309     }
01310 
01311     /**
01312      * multiply this pixel with another one without altering anything...
01313      */
01314     inline trgbPixel<T> operator*(const T c) const {
01315       return trgbPixel<T>(red*c,green*c,blue*c);
01316     }
01317 
01318     /**
01319      * divide by a constant
01320      */
01321     inline trgbPixel<T>& divide(const T c) {
01322       red   /= c;
01323       green /= c;
01324       blue  /= c;
01325       return (*this);
01326     }
01327 
01328     /**
01329      * divide by a constant
01330      */
01331     inline trgbPixel<T> operator/(const T c) const {
01332       return trgbPixel<T>(red/c,green/c,blue/c);
01333     }
01334 
01335     /**
01336      * divide the elements of the other pixel with the given value, and
01337      * leave the result here.
01338      */
01339     inline trgbPixel<T>& divide(const trgbPixel<T>& other, const T val) {
01340       red = other.red/val;
01341       green = other.green/val;
01342       blue = other.blue/val;
01343       return (*this);
01344     }
01345 
01346     /**
01347      * alias for divide
01348      */
01349     inline trgbPixel<T>& operator/=(const T c) {
01350       return divide(c);
01351     }
01352 
01353     /**
01354      * elementwise divide
01355      */
01356     inline trgbPixel<T>& divide(const trgbPixel<T>& c) {
01357       red   /= c.red;
01358       green /= c.green;
01359       blue  /= c.blue;
01360       return (*this);
01361     }
01362 
01363     /**
01364      * Elementwise divide between the elements of a and b
01365      */
01366     trgbPixel<T>& divide(const trgbPixel<T>& a,
01367                          const trgbPixel<T>& b) {
01368 
01369       red   = a.red   / b.red;
01370       green = a.green / b.green;
01371       blue  = a.blue  / b.blue;
01372 
01373       return (*this);
01374     };
01375 
01376     /**
01377      * elementwise divide
01378      */
01379     inline trgbPixel<T> operator/(const trgbPixel<T>& c) const {
01380       trgbPixel tmp(*this);
01381       tmp.divide(c);
01382       return tmp;
01383     }
01384 
01385 
01386     /**
01387      * alias for elementwise divide
01388      */
01389     inline trgbPixel<T>& operator/=(const trgbPixel<T>& c) {
01390       return divide(c);
01391     }
01392 
01393     /**
01394      * obtain the square of the magnitud of this pixel
01395      * \f$red^2+green^2+blue^2 \f$.
01396      */
01397     inline T absSqr() const {
01398       return (red*red+green*green+blue*blue);
01399     }
01400 
01401     /**
01402      * returns the square of the distance of this pixel to the other
01403      * one defined as
01404      * \f$(red-other.red)^2+(green-other.green)^2+(blue-other.blue)^2\f$.
01405      */
01406     inline T distanceSqr(const trgbPixel<T>& other) const {
01407       const T r(red-other.red),g(green-other.green),b(blue-other.blue);
01408       return (r*r+g*g+b*b);
01409     }
01410 
01411     /**
01412      * computes the dot product with another pixel, which is define as
01413      * the sum of the products of all corresponding components, i.e.
01414      * p1.red*p2.red + p1.green*p2.green + p1.blue*p2.blue, where p1 is
01415      * this pixel.
01416      */
01417     inline T dot(const trgbPixel<T>& other) const {
01418       return (red*other.red + green*other.green + blue*other.blue);
01419     }
01420 
01421     /**
01422      * return a normal lti::rgbPixel
01423      * You should ensure that the values are all in a valid interval!
01424      * @see getClippedRGBPixel()
01425      */
01426     inline rgbPixel getRGBPixel() const {
01427       return rgbPixel(static_cast<ubyte>(red),
01428                       static_cast<ubyte>(green),
01429                       static_cast<ubyte>(blue));
01430     }
01431 
01432     /**
01433      * return a normal lti::rgbPixel
01434      * Values lower than 0 are set to 0 and values higher than 255 are set to
01435      * 255.
01436      *
01437      * This method is slower than getRGBPixel() due to the extra comparisons
01438      *
01439      * @see getRGBPixel()
01440      */
01441     inline rgbPixel getClippedRGBPixel() const {
01442       return rgbPixel(static_cast<ubyte>(red<0?0:(red>255?255:red)),
01443                       static_cast<ubyte>(green<0?0:(green>255?255:green)),
01444                       static_cast<ubyte>(blue<0?0:(blue>255?255:blue)));
01445     }
01446 
01447     /**
01448      * apply a C-function to each component of the pixel
01449      * @return a reference to the pixel
01450      */
01451     inline trgbPixel<T>& apply(T (*function)(T)) {
01452       red = (*function)(red);
01453       green = (*function)(red);
01454       blue = (*function)(blue);
01455 
01456       return (*this);
01457     }
01458 
01459     /**
01460      * apply a C-function to each component of the pixel
01461      * @return a reference to the pixel
01462      */
01463     inline trgbPixel<T>& apply(T (*function)(const T&)) {
01464       red = (*function)(red);
01465       green = (*function)(red);
01466       blue = (*function)(blue);
01467 
01468       return (*this);
01469     }
01470 
01471   };
01472 
01473   /**
01474    * alias for trbgPixel<double>
01475    */
01476   typedef trgbPixel<double> drgbPixel;
01477   /**
01478    * alias for trgbPixel<float>
01479    */
01480   typedef trgbPixel<float>  frgbPixel;
01481   /**
01482    * alias for trgbPixel<int>
01483    */
01484   typedef trgbPixel<int>    irgbPixel;
01485 
01486 
01487   /**
01488    * read the vector from the given ioHandler.  The complete flag indicates
01489    * if the enclosing begin and end should be also be readed
01490    *
01491    * @ingroup gStorable
01492    */
01493   template <class T>
01494   bool read(ioHandler& handler,
01495             trgbPixel<T>& p,
01496             const bool complete=true) {
01497     T tmp;
01498     bool b;
01499 
01500     if (complete) {
01501       handler.readBegin();
01502     }
01503 
01504     handler.read(tmp); p.setRed(tmp);
01505     handler.readDataSeparator();
01506     handler.read(tmp); p.setGreen(tmp);
01507     handler.readDataSeparator();
01508     b = handler.read(tmp); p.setBlue(tmp);
01509 
01510     if (complete) {
01511       b = handler.readEnd();
01512     }
01513 
01514     return b;
01515   };
01516 
01517   /**
01518    * write the vector in the given ioHandler.  The complete flag indicates
01519    * if the enclosing begin and end should be also be written or not
01520    *
01521    * @ingroup gStorable
01522    */
01523   template <class T>
01524   bool write(ioHandler& handler,
01525              const trgbPixel<T>& p,
01526              const bool complete=true) {
01527     bool b;
01528 
01529     if (complete) {
01530       handler.writeBegin();
01531     }
01532     handler.write(p.getRed());
01533     handler.writeDataSeparator();
01534     handler.write(p.getGreen());
01535     handler.writeDataSeparator();
01536     b = handler.write(p.getBlue());
01537     if (complete) {
01538       b = handler.writeEnd();
01539     }
01540 
01541     return b;
01542   };
01543 }
01544 
01545 namespace std {
01546   inline ostream& operator<<(ostream& s,const lti::rgbPixel& p) {
01547     s << "(" << int(p.getRed())   << ","
01548       << int(p.getGreen()) << ","
01549       << int(p.getBlue())  << ")";
01550     return s;
01551   };
01552 
01553   //inline ostream& operator>>(istream& s,const lti::rgbPixel& p);
01554   inline istream& operator>>(istream& s,lti::rgbPixel& p) {
01555     char c;
01556     int r,g,b;
01557     s >> c
01558       >> r >> c
01559       >> g >> c
01560       >> b >> c;
01561     p.setRed(static_cast<lti::ubyte>(r));
01562     p.setGreen(static_cast<lti::ubyte>(g));
01563     p.setBlue(static_cast<lti::ubyte>(b));
01564 
01565     return s;
01566   };
01567 
01568   template <class T>
01569   inline ostream& operator<<(ostream& s,const lti::trgbPixel<T>& p) {
01570     s << "("
01571       << p.getRed()   << ","
01572       << p.getGreen() << ","
01573       << p.getBlue()  << ")";
01574     return s;
01575   };
01576 }
01577 
01578 #endif
01579 
01580 
01581 

Generated on Thu Nov 24 16:27:22 2005 for LTI-Lib by Doxygen 1.4.4