LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiRGBPixel.h

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

Generated on Sat Apr 10 15:26:05 2010 for LTI-Lib by Doxygen 1.6.1