Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

GenImage.TCC

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------+
00002  | Library QgarLib, graphics analysis and recognition                  |
00003  | Copyright (C) 2002  Qgar Project, LORIA                             |
00004  |                                                                     |
00005  | This library is free software; you can redistribute it and/or       |
00006  | modify it under the terms of the GNU Lesser General Public          |
00007  | License version 2.1, as published by the Free Software Foundation.  |
00008  |                                                                     |
00009  | This library is distributed in the hope that it will be useful,     |
00010  | but WITHOUT ANY WARRANTY; without even the implied warranty of      |
00011  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                |
00012  | See the GNU Lesser General Public License for more details.         |
00013  |                                                                     |
00014  | The GNU Lesser General Public License is included in the file       |
00015  | LICENSE.LGPL, in the root directory of the Qgar packaging. See      |
00016  | http://www.gnu.org/licenses/lgpl.html for the terms of the licence. |
00017  | To receive a paper copy, write to the Free Software Foundation,     |
00018  | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.       |
00019  |                                                                     |
00020  | Contact Project Qgar for any information:                           |
00021  |   LORIA - équipe Qgar                                               |
00022  |   B.P. 239, 54506 Vandoeuvre-lès-Nancy Cedex, France                |
00023  |   email: qgar-contact@loria.fr                                      |
00024  |   http://www.qgar.org/                                              |
00025  *---------------------------------------------------------------------*/
00026 
00027 
00028 /**
00029  * @file   GenImage.TCC
00030  * @brief  Implementation of function members of class qgar::GenImage.
00031  *
00032  * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a>
00033  * @date   January 27, 2005  21:12
00034  * @since  Qgar 2.2
00035  */
00036 
00037 
00038 
00039 // STD
00040 #include <cmath>
00041 #include <sstream>
00042 #include <string>
00043 // QGAR
00044 #include <qgarlib/array.H>
00045 
00046 
00047 
00048 namespace qgar
00049 {
00050 
00051 
00052 // -------------------------------------------------------------------
00053 // C O N S T R U C T O R S
00054 // -------------------------------------------------------------------
00055 
00056 
00057 // DEFAULT CONSTRUCTOR
00058 
00059 template <class T, template<class> class CheckPolicy>
00060 GenImage<T, CheckPolicy>::GenImage()
00061 
00062   : _bytesPerPixel(sizeof(T)),
00063     _pRefCnt(new int(0)),
00064     _width(0),
00065     _height(0),
00066     _pPixMap(0)
00067 
00068 {
00069   // VOID
00070 }
00071 
00072 
00073 // INITIALIZE WITH GIVEN WIDTH AND HEIGHT
00074 // The pixel map is allocated but is not initialized
00075 
00076 template <class T, template<class> class CheckPolicy>
00077 GenImage<T, CheckPolicy>::GenImage(unsigned int aWidth,
00078                                    unsigned int aHeight)
00079 
00080   : _bytesPerPixel(sizeof(T)),
00081     _pRefCnt(new int(0)),
00082     _width(aWidth),
00083     _height(aHeight)
00084 
00085 {
00086   _pPixMap = new T[aWidth * aHeight];
00087 }
00088 
00089 
00090 // -------------------------------------------------------------------
00091 // C O N S T R U C T O R   F R O M   R A W   D A T A
00092 // -------------------------------------------------------------------
00093 
00094 
00095 // INITIALIZE FROM PIXMAP
00096 
00097 template<class T, template<class> class CheckPolicy>
00098 GenImage<T, CheckPolicy>::GenImage(unsigned int aWidth, 
00099                                    unsigned int aHeight, 
00100                                    T* aPtPixMap)
00101 
00102   throw(QgarErrorInvalidArg)
00103 
00104   : _bytesPerPixel(sizeof(T)),
00105     _pRefCnt(new int(0)),
00106     _width(aWidth),
00107     _height(aHeight),
00108     _pPixMap(aPtPixMap)
00109 
00110 {
00111   // Ensure given pixmap pointer is not null
00112   if (! _pPixMap )
00113     {
00114       throw QgarErrorInvalidArg(__FILE__, __LINE__,
00115                                 "template<class T, template<class> class CheckPolicy> qgar::GenImage<T, CheckPolicy>::GenImage(unsigned int, unsigned int, T*)",                                
00116                                 "Pointer to pixmap cannot be null");
00117     }
00118 
00119   // Ensure that given pixmap conforms to image invariant
00120   checkRange(_pPixMap, _width, BoundingBox(Point(), _width, _height));
00121 }
00122 
00123 
00124 // INITIALIZE FROM FULL DATA
00125 
00126 template <class T, template<class> class CheckPolicy>
00127 GenImage<T, CheckPolicy>::GenImage(unsigned int aBytesCnt,
00128                                    int* aPtRefCnt,
00129                                    unsigned int aWidth,
00130                                    unsigned int aHeight,
00131                                    T* aPtPixMap)
00132 
00133   : _bytesPerPixel(aBytesCnt),
00134     _pRefCnt(aPtRefCnt),
00135     _width(aWidth),
00136     _height(aHeight),
00137     _pPixMap(aPtPixMap)
00138 
00139 {
00140   // Ensure that passed pixmap does not contradict image invariant.
00141   checkRange(_pPixMap, _width, BoundingBox(Point(), _width, _height));
00142 }
00143 
00144 
00145 // -------------------------------------------------------------------
00146 // C O N S T R U C T O R S   F R O M   I M A G E S
00147 // -------------------------------------------------------------------
00148 
00149 
00150 // COPY CONSTRUCTOR
00151 
00152 template <class T, template<class> class CheckPolicy>
00153 GenImage<T, CheckPolicy>::GenImage(const GenImage& anImg)
00154 
00155   : _bytesPerPixel(anImg._bytesPerPixel),
00156     _pRefCnt(new int(0)),
00157     _width(anImg._width),
00158     _height(anImg._height)
00159 
00160 {
00161   int size = _width * _height;
00162   _pPixMap = new T[size];
00163   memcpy(_pPixMap, anImg._pPixMap, size * sizeof(T));
00164 }
00165 
00166 
00167 // CONVERSION FROM AN IMAGE HAVING SAME PIXEL TYPE 'T'
00168 // BUT DIFFERENT POLICIES
00169 
00170 template <class T, template<class> class CheckPolicy>
00171 template <template<class> class OtherCheckPolicy>
00172 GenImage<T, CheckPolicy>::GenImage(const GenImage<T, OtherCheckPolicy>& anImg)
00173 
00174   : _bytesPerPixel(anImg.bytesPerPixel()),
00175     _pRefCnt(new int(0)),
00176     _width(anImg.width() ),
00177     _height(anImg.height() )
00178 
00179 {
00180   // Ensure that passed pixmap does not contradict image invariant.
00181   checkRange(anImg.pPixMap(), _width, BoundingBox(Point(), _width, _height));
00182 
00183   int size = _width * _height;
00184   _pPixMap = new T[size];
00185   memcpy(_pPixMap, anImg.pPixMap(), size * sizeof(T));
00186 }
00187 
00188 
00189 // INITIALIZE FROM AN IMAGE WITH PIXELS OF A TYPE DIFFERENT FROM 'T'
00190 
00191 template<class T, template<class> class CheckPolicy>
00192 template<class U, template<class> class UCheck>
00193 GenImage<T, CheckPolicy>::GenImage(const GenImage<U, UCheck>& anImg)
00194 
00195   : _bytesPerPixel(sizeof(T)),
00196     _pRefCnt(new int(0)),
00197     _width(anImg.width()),
00198     _height(anImg.height())
00199 
00200 {
00201   int size = _width * _height;
00202   _pPixMap = new T[size];
00203   
00204   U* pMapFrom = anImg.pPixMap();
00205   T* pMapTo   = _pPixMap;
00206   for (int iCnt = 0; iCnt < size ; ++iCnt, ++pMapTo, ++pMapFrom)
00207     {
00208       *pMapTo = static_cast<T>(*pMapFrom);
00209     }
00210 
00211   // Ensure that passed pixmap does not contradict image invariant.
00212   checkRange(_pPixMap, _width, BoundingBox(Point(), _width, _height));
00213 }
00214 
00215 
00216 // INITIALIZE BY COPYING A BOUNDING BOX OF A GIVEN IMAGE
00217 //
00218 // The bounding box defines a rectangular area whose sides are parallel
00219 // to the coordinate axis.
00220 // The intersection between this rectangle and the given image must be
00221 // non-empty. If the overlaping zone is only partial, the non-overlaping
00222 // zones are filled with pixels having value 'aPixVal'
00223 
00224 template<class T, template<class> class CheckPolicy>
00225 template<template<class> class OtherCheckPolicy>
00226 GenImage<T, CheckPolicy>::GenImage(const GenImage<T, OtherCheckPolicy>& anImg,
00227                                    const BoundingBox& aBox,
00228                                    T aPixVal)
00229 
00230   : _bytesPerPixel(anImg.bytesPerPixel()),
00231     _pRefCnt(new int(0)),
00232     _width(aBox.width()),
00233     _height(aBox.height()),
00234     _pPixMap(new T[aBox.width() * aBox.height()])
00235 
00236 {
00237   copyBox(anImg,
00238           aBox.xTopLeft(),
00239           aBox.yTopLeft(),
00240           aBox.xBottomRight(),
00241           aBox.yBottomRight(),
00242           aPixVal);
00243 
00244   // Ensure that modified pixmap does not contradict image invariant.
00245   checkRange(_pPixMap, _width, aBox);
00246 }
00247 
00248 
00249 // INITIALIZE BY COPYING A RECTANGULAR AREA OF A GIVEN IMAGE
00250 //
00251 // The rectangle sides are parallel to the coordinate axis.
00252 // The intersection between the rectangle and the given image must be
00253 // non-empty. If the overlaping zone is only partial, the non-overlaping
00254 // zones are filled with pixels having value 'aPixVal'
00255 
00256 template <class T, template<class> class CheckPolicy>
00257 template <template<class> class OtherCheckPolicy>
00258 GenImage<T, CheckPolicy>::GenImage(const GenImage<T, OtherCheckPolicy>& anImg,
00259                                    unsigned int aXTopLeft,
00260                                    unsigned int aYTopLeft,
00261                                    unsigned int aXBottomRight,
00262                                    unsigned int aYBottomRight,
00263                                    T aPixVal)
00264 
00265   : _bytesPerPixel(anImg.bytesPerPixel()),
00266     _pRefCnt(new int(0)),
00267     _width(aXBottomRight - aXTopLeft + 1),
00268     _height(aYBottomRight - aYTopLeft + 1 ),
00269     _pPixMap(new T[  (aXBottomRight - aXTopLeft + 1) 
00270                    * (aYBottomRight - aYTopLeft + 1)])
00271 
00272 {
00273   copyBox(anImg,
00274           aXTopLeft,
00275           aYTopLeft,
00276           aXBottomRight,
00277           aYBottomRight,
00278           aPixVal);
00279 
00280   // Ensure that passed pixmap does not contradict image invariant.
00281   checkRange(_pPixMap,
00282              _width,
00283              BoundingBox(aXTopLeft, aYTopLeft, aXBottomRight, aYBottomRight));
00284 }
00285 
00286 
00287 // -------------------------------------------------------------------
00288 // C O N S T R U C T O R S   F R O M   I M A G E   F I L E S
00289 // -------------------------------------------------------------------
00290 
00291 
00292 // INITIALIZE WITH AN IMAGE FROM A PBM+ FILE
00293 
00294 template <class T, template<class> class CheckPolicy>
00295 GenImage<T, CheckPolicy>::GenImage(AbstractPbmPlusFile& aPbmPlusFile)
00296 
00297   : _pRefCnt(new int(0))
00298 
00299 {
00300   aPbmPlusFile.openRONLY();
00301 
00302   _width   = aPbmPlusFile.colCnt();
00303   _height  = aPbmPlusFile.rowCnt();
00304   _pPixMap = new T[_height * _width];
00305 
00306   unsigned char* ptRow = aPbmPlusFile.pRow();
00307   for (int rowIdx = 0 ; rowIdx < _height ; ++rowIdx)
00308     {
00309       aPbmPlusFile.readRow();
00310       setRow(rowIdx, ptRow);
00311     }
00312 
00313   aPbmPlusFile.close();
00314 }
00315 
00316 
00317 // -------------------------------------------------------------------
00318 // D E S T R U C T O R 
00319 // -------------------------------------------------------------------
00320 
00321 
00322 template <class T, template<class> class CheckPolicy>
00323 GenImage<T, CheckPolicy>::~GenImage()
00324 {
00325   if (*_pRefCnt == 0)
00326     {
00327       // The space allocated to the pixel map is not shared with another object
00328       delete [] _pPixMap;
00329       delete _pRefCnt;
00330     }
00331   else
00332     {
00333       // The space allocated to the pixel map is shared with at least
00334       // one other object: Just decrement the reference counter
00335       (*_pRefCnt)--;
00336     }
00337 }
00338 
00339 
00340 // -------------------------------------------------------------------
00341 // A C C E S S   T O   I M A G E   C H A R A C T E R I S T I C S
00342 // -------------------------------------------------------------------
00343 
00344 
00345 // GET THE IMAGE WIDTH
00346 
00347 template <class T, template<class> class CheckPolicy>
00348 inline int
00349 GenImage<T, CheckPolicy>::width() const
00350 {
00351   return _width;
00352 }
00353 
00354 
00355 // GET THE IMAGE HEIGHT
00356 
00357 template <class T, template<class> class CheckPolicy>
00358 inline int
00359 GenImage<T, CheckPolicy>::height() const
00360 {
00361   return _height;
00362 }
00363 
00364 
00365 // GET THE NUMBER OF BYTES PER PIXEL
00366 
00367 template <class T, template<class> class CheckPolicy>
00368 inline int
00369 GenImage<T, CheckPolicy>::bytesPerPixel() const
00370 {
00371   return _bytesPerPixel;
00372 }
00373 
00374 
00375 // -------------------------------------------------------------------
00376 // A C C E S S   T O   P I X E L   V A L U E S
00377 // -------------------------------------------------------------------
00378 
00379 
00380 // GET A PIXEL VALUE
00381 
00382 template <class T, template<class> class CheckPolicy>
00383 T
00384 GenImage<T, CheckPolicy>::pixel(unsigned int aX,
00385                                 unsigned int aY)
00386   const
00387 {
00388   return *(_pPixMap + (aY * _width) + aX);
00389 }
00390 
00391 
00392 // FILL A GIVEN ARRAY WITH A ROW OF PIXELS
00393 
00394 template <class T, template<class> class CheckPolicy>
00395 void
00396 GenImage<T, CheckPolicy>::row(unsigned int aRowIdx,
00397                               T* aRow)
00398   const
00399 {
00400   memcpy(aRow, _pPixMap + (aRowIdx * _width), _width * sizeof(T));
00401 }
00402 
00403 
00404 // GET A COLUMN OF PIXELS
00405 
00406 template <class T, template<class> class CheckPolicy>
00407 void
00408 GenImage<T, CheckPolicy>::column(unsigned int aColIdx,
00409                                  T* aCol)
00410   const
00411 {
00412   T* pMap = _pPixMap + aColIdx;
00413   T* pCol  = aCol;
00414   for (int iCnt = 0;
00415        iCnt < _height ;
00416        ++iCnt, ++pCol, pMap += _width)
00417     {
00418       *pCol = *pMap;
00419     }
00420 }
00421 
00422 
00423 // -------------------------------------------------------------------
00424 // ACCESS TO DIRECT TRANSFORMATIONS OF THE PIXEL MAP
00425 // -------------------------------------------------------------------
00426 
00427 
00428 // GET A POINTER ON A GIVEN PIXEL
00429 
00430 template <class T, template<class> class CheckPolicy>
00431 inline T*
00432 GenImage<T, CheckPolicy>::pPixel(unsigned int aRowIdx,
00433                                  unsigned int aColIdx) const
00434 {
00435   return _pPixMap + (aRowIdx * _width) + aColIdx;
00436 }
00437 
00438 
00439 // GET A POINTER ON A ROW OF PIXELS
00440 
00441 template <class T, template<class> class CheckPolicy>
00442 inline T*
00443 GenImage<T, CheckPolicy>::pRow(unsigned int aRowIdx) const
00444 {
00445   return _pPixMap + (aRowIdx * _width);
00446 }
00447 
00448 
00449 // GET A POINTER ON A COLUMN OF PIXELS
00450 
00451 template <class T, template<class> class CheckPolicy>
00452 inline T*
00453 GenImage<T, CheckPolicy>::pColumn(unsigned int aColIdx) const
00454 {
00455   return _pPixMap + aColIdx;
00456 }
00457 
00458 
00459 // GET THE POINTER TO THE PIXEL MAP
00460 
00461 template <class T, template<class> class CheckPolicy>
00462 inline T*
00463 GenImage<T, CheckPolicy>::pPixMap() const
00464 {
00465   return _pPixMap;
00466 }
00467 
00468 
00469 // -------------------------------------------------------------------
00470 // S E T   P I X E L   V A L U E S
00471 // -------------------------------------------------------------------
00472 
00473 
00474 // SET A PIXEL VALUE
00475 
00476 template <class T, template<class> class CheckPolicy>
00477 void
00478 GenImage<T, CheckPolicy>::setPixel(unsigned int aX,
00479                                    unsigned int aY,
00480                                    T aPixVal)
00481 {
00482   *(_pPixMap + (aY * _width) + aX) = aPixVal;
00483 
00484   // Ensure that new pixel value does not contradict image invariant.
00485   checkRange(_pPixMap, _width, BoundingBox(aX, aY, 1, 1));
00486 }
00487 
00488 
00489 // SET A ROW OF PIXELS
00490 
00491 template <class T, template<class> class CheckPolicy>
00492 void
00493 GenImage<T, CheckPolicy>::setRow(unsigned int aRowIdx,
00494                                  const T* const aRow)
00495 {
00496   memcpy(_pPixMap + (aRowIdx * _width), aRow, _width * sizeof(T));
00497 
00498   // Ensure that new row does not contradict pixel invariant.
00499   checkRange(_pPixMap + (aRowIdx * _width), _width, 
00500              BoundingBox(Point(), _width, _height));
00501 }
00502 
00503 
00504 // SET A COLUMN OF PIXELS
00505 
00506 template <class T, template<class> class CheckPolicy>
00507 void
00508 GenImage<T, CheckPolicy>::setColumn(unsigned int aColIdx,
00509                                     const T* const aCol)
00510 {
00511   T* pMapTo = _pPixMap + aColIdx;
00512   const T* pCol  = aCol;
00513   for (int iCnt = 0;
00514        iCnt < _height ;
00515        ++iCnt, ++pCol, pMapTo += _width)
00516     {
00517       *pMapTo = *pCol;
00518     }
00519 
00520   // Ensure that the new column does not contradict invariant.
00521   checkRange(_pPixMap, _width, BoundingBox(Point(), 1, _height));
00522 }
00523 
00524 
00525 // -------------------------------------------------------------------
00526 // D R A W   I N   T H E   P I X E L   M A P
00527 // -------------------------------------------------------------------
00528 
00529 
00530 // Bresenham's algorithm is used
00531 // Pixels are set to value 'aPixVal'
00532 
00533 template <class T, template<class> class CheckPolicy>
00534 void
00535 GenImage<T, CheckPolicy>::draw(const Segment& aSeg, T aPixVal)
00536 {
00537   Point p1 = aSeg.source();
00538   Point p2 = aSeg.target();
00539     
00540   int x;
00541   int y;
00542   int xlast;
00543   int ylast;
00544     
00545   int dx = (int)(std::fabs((double)p2.x() - p1.x())); // Delta x
00546   int dy = (int)(std::fabs((double)p2.y() - p1.y())); // Delta y
00547     
00548   if (dx > dy)
00549     {
00550       // Main axis Ox
00551       if (p1.x() < p2.x())
00552         {
00553           // find out where to start and where to end
00554           x     = p1.x();
00555           y     = p1.y();
00556           xlast = p2.x();
00557           ylast = p2.y();
00558         }
00559       else
00560         {
00561           x     = p2.x();
00562           y     = p2.y();
00563           xlast = p1.x();
00564           ylast = p1.y();
00565         }
00566 
00567       int e = (dy << 1) - dx; // Initialize
00568       if (y < ylast)
00569         {       
00570           for (int iCnt = 0 ; iCnt < dx ; ++iCnt)
00571             {
00572               // Write if in image
00573               if ((x > 0) && (x < _width) && (y > 0) && (y < _height))
00574                 {
00575                   setPixel(x, y, aPixVal);
00576                 }
00577               if (e > 0)
00578                 {
00579                   ++y;
00580                   e += (dy << 1) - (dx << 1);
00581                 }
00582               else
00583                 {
00584                   e += (dy << 1);
00585                 }
00586               ++x;
00587             }
00588         }
00589       else
00590         {
00591           for (int iCnt = 0 ; iCnt < dx ; ++iCnt)
00592             {
00593               // Write if in image
00594               if ((x > 0) && (x < _width) && (y > 0) && (y < _height))
00595                 {
00596                   setPixel(x, y, aPixVal);
00597                 }
00598               if (e > 0)
00599                 {
00600                   --y;
00601                   e += (dy << 1) - (dx << 1);
00602                 }
00603               else
00604                 {
00605                   e += (dy << 1);
00606                 }
00607               ++x;
00608             }
00609         }
00610     }
00611   else
00612     {
00613       // Main axis Oy
00614       if (p1.y() < p2.y())
00615         {
00616           x     = p1.x();
00617           y     = p1.y();
00618           xlast = p2.x();
00619           ylast = p2.y();
00620         }
00621       else
00622         {
00623           x = p2.x();
00624           y = p2.y();
00625           xlast = p1.x();
00626           ylast = p1.y();
00627           }
00628       
00629       int e = (dx << 1) - dy;
00630       if (x < xlast)
00631         {
00632           for (int iCnt =0 ; iCnt < dy ; ++iCnt)
00633             {
00634               // Write if in image
00635               if ((x > 0) && (x < _width) && (y > 0) && (y < _height))
00636                 {
00637                   setPixel(x, y, aPixVal);
00638                 }
00639 
00640               if (e > 0)
00641                 {
00642                   ++x;
00643                   e += (dx << 1) - (dy << 1);
00644                 }
00645               else
00646                 {
00647                   e += (dx << 1);
00648                 }
00649               ++y;
00650             }
00651         }
00652       else
00653         {
00654           for (int iCnt = 0 ; iCnt < dy ; ++iCnt)
00655             {
00656               if ((x > 0) && (x < _width) && (y > 0) && (y < _height)) 
00657                 {
00658                   setPixel(x, y, aPixVal);
00659                 }
00660 
00661               if (e > 0)
00662                 {
00663                   --x;
00664                   e += (dx << 1) - (dy << 1);
00665                 }
00666               else
00667                 {
00668                   e += (dx << 1);
00669                 }
00670               ++y;
00671             }
00672         }
00673     }
00674 
00675   if ((xlast > 0) && (xlast < _width) && (ylast > 0) && (ylast < _height)) 
00676     {
00677       setPixel(xlast, ylast, aPixVal); // write last pixel
00678     }
00679 }
00680 
00681 
00682 // -------------------------------------------------------------------
00683 // C O P Y
00684 // -------------------------------------------------------------------
00685 
00686 
00687 // SHALLOW COPY: THE PIXEL MAP OF THE CURRENT IMAGE IS NOT DUPLICATED
00688 
00689 template <class T, template<class> class CheckPolicy>
00690 GenImage<T, CheckPolicy>
00691 GenImage<T, CheckPolicy>::shallowCopy()
00692 {
00693   (*_pRefCnt)++;
00694 
00695   return GenImage<T, CheckPolicy>(_bytesPerPixel,
00696                                   _pRefCnt,
00697                                   _width,
00698                                   _height,
00699                                   _pPixMap);
00700 }
00701 
00702 
00703 // -------------------------------------------------------------------
00704 // A S S I G N M E N T
00705 // -------------------------------------------------------------------
00706 
00707 
00708 // ASSIGN GIVEN IMAGE TO CURRENT IMAGE: PERFORM A DEEP COPY
00709 
00710 template <class T, template<class> class CheckPolicy>
00711 GenImage<T, CheckPolicy>& 
00712 GenImage<T, CheckPolicy>::operator=(const GenImage& anImg)
00713 {
00714   if (this != &anImg)
00715     {
00716       _width  = anImg.width();
00717       _height = anImg.height();
00718 
00719       // Free the current pixel map and allocate a new one
00720       delete [] _pPixMap;
00721       int size = _width * _height;
00722       _pPixMap = new T[size];
00723 
00724       // Copy the pixel map
00725       memcpy(_pPixMap, anImg.pPixMap(), size * sizeof(T));
00726     }
00727   return *this;
00728 }
00729 
00730 
00731 // ASSIGN GIVEN IMAGE TO CURRENT IMAGE: PERFORM A DEEP COPY
00732 
00733 template <class T, template<class> class CheckPolicy>
00734 template<template <class> class OtherCheckPolicy>
00735 GenImage<T, CheckPolicy>& 
00736 GenImage<T, CheckPolicy>::operator=(const GenImage<T, OtherCheckPolicy>& anImg)
00737 {
00738   // Ensure that rhs pixmap does not contradict lhs invariant.
00739   checkRange(anImg.pPixMap(), anImg.width(), 
00740              BoundingBox(Point(), anImg.width(), anImg.height()));
00741 
00742   _width  = anImg.width();
00743   _height = anImg.height();
00744 
00745   // Free the current pixel map and allocate a new one
00746   delete [] _pPixMap;
00747   int size = _width * _height;
00748   _pPixMap = new T[size];
00749 
00750   // Copy the pixel map
00751   memcpy(_pPixMap, anImg.pPixMap(), size * sizeof(T));
00752   
00753   return *this;
00754 }
00755 
00756 
00757 // -------------------------------------------------------------------
00758 // I M A G E   A D D I T I O N S
00759 // -------------------------------------------------------------------
00760 
00761 
00762 // ADD 2 IMAGES: THE ADDITION IS NOT NORMALIZED
00763 
00764 template <class T, template<class> class CheckPolicy>
00765 template<template<class> class OtherCheckPolicy>
00766 GenImage<T, GenImage_NoCheck> 
00767 GenImage<T, CheckPolicy>::operator+(const GenImage<T, OtherCheckPolicy>& anImg) const
00768 {
00769   return plus(anImg);
00770 }
00771 
00772 
00773 // ADD TO CURRENT IMAGE: THE ADDITION IS NOT NORMALIZED
00774 
00775 template <class T, template<class> class CheckPolicy>
00776 template<template<class> class OtherCheckPolicy>
00777 GenImage<T, CheckPolicy>& 
00778 GenImage<T, CheckPolicy>::operator+=(const GenImage<T, OtherCheckPolicy>& anImg)
00779 {
00780   return plusEqual(anImg);
00781 }
00782 
00783 
00784 // ADD 2 IMAGES: THE ADDITION IS NOT NORMALIZED
00785 template <class T, template<class> class CheckPolicy>
00786 template<template<class> class OtherCheckPolicy>
00787 GenImage<T, GenImage_NoCheck>
00788 GenImage<T, CheckPolicy>::plus(const GenImage<T, OtherCheckPolicy>& anImg) const
00789 {
00790   return GenImage(*this).plusEqual(anImg);
00791 }
00792 
00793 // ADD TO CURRENT IMAGE: THE ADDITION IS NOT NORMALIZED
00794 template <class T, template<class> class CheckPolicy>
00795 template<template<class> class OtherCheckPolicy>
00796 GenImage<T, CheckPolicy>&
00797 GenImage<T, CheckPolicy>::plusEqual(const GenImage<T, OtherCheckPolicy>& anImg)
00798 
00799   throw(QgarErrorDomain)
00800 
00801 {
00802   if ((_width != anImg.width()) || (_height != anImg.height()))
00803     {
00804       // Image sizes do not match
00805       std::ostringstream os;
00806       os << "Size of image to be added ["
00807          << anImg.width()
00808          << " X "
00809          << anImg.height()
00810          << "] is different from current image size ["
00811          << _width
00812          << " X "
00813          << _height
00814          << "]";
00815 
00816       throw QgarErrorDomain(__FILE__, __LINE__,
00817                             "template <class T, template<class> class CheckPolicy> template<template<class> class OtherCheckPolicy> qgar::GenImage<T, CheckPolicy>& qgar::GenImage<T, CheckPolicy>::plusEqual(const qgar::GenImage<T, OtherCheckPolicy>&)",
00818                             os.str());
00819     }
00820 
00821   T* pMapTo  = _pPixMap;
00822   T* pMapFrom = anImg.pPixMap();
00823   int size  = _width * _height;
00824   for (int iCnt = 0 ; iCnt < size ; ++iCnt, ++pMapTo, ++pMapFrom)
00825     {
00826       *pMapTo += *pMapFrom;
00827     }
00828 
00829   // Ensure that pixmap after operation still conforms to the invariant.
00830   checkRange(_pPixMap, _width, BoundingBox(Point(), _width, _height));
00831   
00832   return *this;
00833 }
00834 
00835 
00836 // -------------------------------------------------------------------
00837 // I M A G E   S U B T R A C T I O N
00838 // -------------------------------------------------------------------
00839 
00840 
00841 // SUBTRACT 2 IMAGES: THE SUBTRACTION IS NOT NORMALIZED
00842 
00843 template <class T, template<class> class CheckPolicy>
00844 template<template<class> class OtherCheckPolicy>
00845 GenImage<T, GenImage_NoCheck> 
00846 GenImage<T, CheckPolicy>::operator-(const GenImage<T, OtherCheckPolicy>& anImg) const
00847 {
00848   return minus(anImg);
00849 }
00850 
00851 
00852 // SUBTRACT TO CURRENT IMAGE: THE ADDITION IS NOT NORMALIZED
00853 
00854 template <class T, template<class> class CheckPolicy>
00855 template<template<class> class OtherCheckPolicy>
00856 GenImage<T, CheckPolicy>& 
00857 GenImage<T, CheckPolicy>::operator-=(const GenImage<T, OtherCheckPolicy>& anImg)
00858 {
00859   return minusEqual(anImg);
00860 }
00861 
00862 
00863 // SUBTRACT 2 IMAGES: THE SUBTRACTION IS NOT NORMALIZED
00864 template <class T, template<class> class CheckPolicy>
00865 template<template<class> class OtherCheckPolicy>
00866 GenImage<T, GenImage_NoCheck> 
00867 GenImage<T, CheckPolicy>::minus(const GenImage<T, OtherCheckPolicy>& anImg) const
00868 {
00869   // Create a copy of the current image and subtract the given image to it
00870   return GenImage(*this).minusEqual(anImg);
00871 }
00872 
00873 // SUBTRACT TO CURRENT IMAGE: THE SUBTRACTION IS NOT NORMALIZED
00874 template <class T, template<class> class CheckPolicy>
00875 template<template<class> class OtherCheckPolicy>
00876 GenImage<T, CheckPolicy>& 
00877 GenImage<T, CheckPolicy>::minusEqual(const GenImage<T, OtherCheckPolicy>& anImg)
00878 
00879   throw(QgarErrorDomain)
00880 
00881 {
00882   if ((_width != anImg.width()) || (_height != anImg.height()))
00883     {
00884       // Image sizes do not match
00885       std::ostringstream os;
00886       os << "Size of image to be added ["
00887          << anImg.width()
00888          << " X "
00889          << anImg.height()
00890          << "] is different from current image size ["
00891          << _width
00892          << " X "
00893          << _height
00894          << "]";
00895 
00896       throw QgarErrorDomain(__FILE__, __LINE__,
00897                             "template <class T, template<class> class CheckPolicy> template<template<class> class OtherCheckPolicy> qgar::GenImage<T, CheckPolicy>& qgar::GenImage<T, CheckPolicy>::minusEqual(const qgar::GenImage<T, OtherCheckPolicy>&)",
00898                             os.str());
00899     }
00900 
00901   T* pMapTo  = _pPixMap;
00902   T* pMapFrom = anImg.pPixMap();
00903   int size  = _width * _height;
00904   for (int iCnt = 0 ; iCnt < size ; ++iCnt, ++pMapTo, ++pMapFrom)
00905     {
00906       *pMapTo -= *pMapFrom;
00907     }
00908 
00909   // Ensure that pixmap after operation still conforms to the invariant.
00910   checkRange(_pPixMap, _width, BoundingBox(Point(), _width, _height));
00911 
00912   return *this;
00913 }
00914 
00915 
00916 // -------------------------------------------------------------------
00917 // I M A G E   M U L T I P L I C A T I O N
00918 // -------------------------------------------------------------------
00919 
00920 
00921 // MULTIPLY 2 IMAGES: THE MULTIPLICATION IS NOT NORMALIZED
00922 
00923 template <class T, template<class> class CheckPolicy>
00924 template<template<class> class OtherCheckPolicy>
00925 GenImage<T, GenImage_NoCheck> 
00926 GenImage<T, CheckPolicy>::operator*(const GenImage<T, OtherCheckPolicy>& anImg) const
00927 {
00928   return times(anImg);
00929 }
00930 
00931 
00932 // MULTIPLY BY GIVEN IMAGE: THE MULTIPLICATION IS NOT NORMALIZED
00933 
00934 template <class T, template<class> class CheckPolicy>
00935 template<template<class> class OtherCheckPolicy>
00936 GenImage<T, CheckPolicy>&
00937 GenImage<T, CheckPolicy>::operator*=(const GenImage<T, OtherCheckPolicy>& anImg)
00938 {
00939   return timesEqual(anImg);
00940 }
00941 
00942 
00943 // MULTIPLY 2 IMAGES: THE MULTIPLICATION IS NOT NORMALIZED
00944 template <class T, template<class> class CheckPolicy>
00945 template<template<class> class OtherCheckPolicy>
00946 GenImage<T, GenImage_NoCheck>
00947 GenImage<T, CheckPolicy>::times(const GenImage<T, OtherCheckPolicy>& anImg) const
00948 {
00949   // Create a copy of the current image and multiply the given image to it
00950   return GenImage(*this).timesEqual(anImg);
00951 }
00952 
00953 
00954 // MULTIPLY BY GIVEN IMAGE: THE MULTIPLICATION IS NOT NORMALIZED
00955 template <class T, template<class> class CheckPolicy>
00956 template<template<class> class OtherCheckPolicy>
00957 GenImage<T, CheckPolicy>&
00958 GenImage<T, CheckPolicy>::timesEqual(const GenImage<T, OtherCheckPolicy>& anImg)
00959 
00960   throw(QgarErrorDomain)
00961 
00962 {
00963 
00964   if ((_width != anImg.width()) || (_height != anImg.height()))
00965     {
00966       // Image sizes do not match
00967       std::ostringstream os;
00968       os << "Size of image to be added ["
00969          << anImg.width()
00970          << " X "
00971          << anImg.height()
00972          << "] is different from current image size ["
00973          << _width
00974          << " X "
00975          << _height
00976          << "]";
00977 
00978       throw QgarErrorDomain(__FILE__, __LINE__,
00979                             "template <class T, template<class> class CheckPolicy> template<template<class> class OtherCheckPolicy> qgar::GenImage<T, CheckPolicy>& qgar::GenImage<T, CheckPolicy>::timesEqual(const qgar::GenImage<T, OtherCheckPolicy>&)",
00980                             os.str());
00981     }
00982 
00983   T* pMapTo   = _pPixMap;
00984   T* pMapFrom = anImg.pPixMap();
00985   int size  = _width * _height;
00986   for (int iCnt = 0 ; iCnt < size ; iCnt++, ++pMapTo, ++pMapFrom)
00987     {
00988       *pMapTo *= *pMapFrom;
00989     }
00990 
00991   // Ensure that pixmap after operation still conforms to the invariant.
00992   checkRange(_pPixMap, _width, BoundingBox(Point(), _width, _height));
00993 
00994   return *this;
00995 }
00996 
00997 
00998 // -------------------------------------------------------------------
00999 // F I L E   S T O R A G E
01000 // -------------------------------------------------------------------
01001 
01002 
01003 template <class T, template<class> class CheckPolicy>
01004 void
01005 GenImage<T, CheckPolicy>::save(AbstractPbmPlusFile& aPbmPlusFile) const
01006 {
01007   // Update image width and height BEFORE writing file header
01008   aPbmPlusFile.setColCnt(_width);
01009   aPbmPlusFile.setRowCnt(_height);
01010 
01011   // Open file and write header
01012   aPbmPlusFile.openWONLY();
01013   
01014   // Dump image
01015   unsigned char* ptRow = aPbmPlusFile.pRow();
01016   for (int rowIdx = 0 ; rowIdx < _height ; ++rowIdx)
01017     {
01018       row(rowIdx, ptRow);
01019       aPbmPlusFile.writeRow();
01020     }
01021 
01022   // Write footer and close file
01023   aPbmPlusFile.close();
01024 }
01025 
01026 
01027 // -------------------------------------------------------------------
01028 // B O R D E R   M I R R O R I N G
01029 // -------------------------------------------------------------------
01030 
01031 
01032 // MIRROR BORDER ROWS FOR CONVOLUTIONS
01033 
01034 template <class T, template<class> class CheckPolicy>
01035 int
01036 GenImage<T, CheckPolicy>::borderRows(int aRowIdx) const
01037 { 
01038   return (aRowIdx < 0)
01039          ? -aRowIdx 
01040          : (
01041              (aRowIdx < _height)
01042              ? aRowIdx
01043              : (_height - aRowIdx + _height - 2)
01044            );
01045 }
01046 
01047 
01048 // MIRROR BORDER COLUMNS FOR CONVOLUTIONS
01049 
01050 template <class T, template<class> class CheckPolicy>
01051 int
01052 GenImage<T, CheckPolicy>::borderCols(int aColIdx) const
01053 {
01054   return (aColIdx < 0)
01055           ? -aColIdx 
01056           : (
01057               (aColIdx < _width)
01058               ? aColIdx
01059               : (_width - aColIdx + _width - 2)
01060             );
01061 }
01062 
01063 
01064 // -------------------------------------------------------------------
01065 // A U X I L I A R I E S 
01066 // -------------------------------------------------------------------
01067 
01068 
01069 // PERFORM THE COPY OF A RECTANGULAR ZONE OF A GIVEN IMAGE
01070 // INTO THE CURRENT IMAGE
01071 
01072 template <class T, template<class> class CheckPolicy>
01073 void 
01074 GenImage<T, CheckPolicy>::copyBox(const GenImage<T, CheckPolicy>& anImg,
01075                                   unsigned int aXTopLeft,
01076                                   unsigned int aYTopLeft,
01077                                   unsigned int aXBottomRight,
01078                                   unsigned int aYBottomRight,
01079                                   T aPixVal)
01080 { 
01081   T*  pMapTo  = _pPixMap;   // Pointer to the current image
01082   int rowTo   = 0;          // Row index in current image
01083   int rowFrom = aYTopLeft;  // Row index in given image
01084   
01085   // Fill non-overlaping rows (if any)
01086   for ( ; rowFrom < 0 ; ++rowTo, ++rowFrom)
01087     {
01088       qgFill(pMapTo, _width, aPixVal);
01089     }
01090   
01091   // Pointer to the first significant pixel in the given image
01092   T* pMapFrom = anImg.pPixMap() + (rowFrom * anImg.width());
01093 
01094   // Copy significant pixels from the rectangle into the current image
01095   for ( ;            
01096        (rowTo < _height) && (rowFrom < anImg.height()) ;
01097        ++rowTo, ++rowFrom)
01098     {
01099       int currCol = 0;
01100       int imgCol = aXTopLeft;
01101       
01102       // Fill non-overlaping rows (if any)
01103       for ( ; imgCol < 0 ; ++currCol, ++imgCol, ++pMapTo)
01104         {
01105           *pMapTo = aPixVal;
01106         }
01107 
01108 
01109       pMapFrom = anImg.pPixMap() + (rowFrom * anImg.width()) + imgCol;
01110       for ( ;
01111            (currCol < _width) && (imgCol < anImg.width()) ;
01112            ++currCol, ++imgCol, ++pMapTo, ++pMapFrom)
01113         {
01114             *pMapTo = *pMapFrom;
01115         }
01116 
01117       // Fill non-overlaping rows (if any)
01118       qgFill(pMapTo, _width - currCol, aPixVal);
01119     } // END copy of the significant pixels
01120 
01121   // Fill non-overlaping rows (if any)
01122   for ( ; rowTo < _height ; ++rowTo)            
01123     {
01124       qgFill(pMapTo, _width, aPixVal);
01125     }
01126 }
01127 
01128 
01129 // -------------------------------------------------------------------
01130 
01131 
01132 } // namespace qgar