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

LinDilatedImage.C

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  LinDilatedImage.C
00030  * @brief Implementation of class qgar::LinDilatedImage.
00031  *
00032  *        See file LinDilatedImage.H for the interface.
00033  *
00034  * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Mathieu Baeumler">Mathieu Baeumler</a>
00035  * @date   August 5, 2002  16:52
00036  * @since  Qgar 2.0
00037  */
00038 
00039 
00040 
00041 // STD
00042 #include <algorithm>
00043 #include <sstream>
00044 // QGAR
00045 #include <qgarlib/GenImage.H>
00046 #include <qgarlib/LinDilatedImage.H>
00047 #include <qgarlib/QgarErrorDomain.H>
00048 
00049 
00050 
00051 namespace qgar
00052 {
00053 
00054 // -------------------------------------------------------------------
00055 // C O N S T R U C T O R
00056 // -------------------------------------------------------------------
00057 
00058 LinDilatedImage::LinDilatedImage(GreyLevelImage& anImg,
00059                                  QGEorientation anOrient,
00060                                  unsigned int aDilSize)
00061   throw(QgarErrorDomain)
00062 
00063  : GreyLevelImage(anImg)
00064 
00065 {
00066   perform(this, anOrient, aDilSize);
00067 }
00068 
00069 // -------------------------------------------------------------------
00070 // L I N E A R   D I L A T I O N S
00071 // -------------------------------------------------------------------
00072   
00073 
00074 void LinDilatedImage::perform(GreyLevelImage* anImg,
00075                               QGEorientation anOrient,
00076                               unsigned int aDilSize)
00077 {
00078   switch (anOrient)
00079     {
00080     case QGE_ORIENTATION_HOR:
00081       dilateHor(anImg, aDilSize);
00082       break;
00083     case QGE_ORIENTATION_VER:
00084       dilateVer(anImg, aDilSize);
00085       break;
00086     case QGE_ORIENTATION_DIAG_POS:
00087       dilatePdiag(anImg, aDilSize);
00088       break;
00089     case QGE_ORIENTATION_DIAG_NEG:
00090       dilateNdiag(anImg, aDilSize);
00091       break;
00092     case QGE_ORIENTATION_ALL:
00093       dilateAll(anImg, aDilSize);
00094     }
00095 }
00096 
00097 // -------------------------------------------------------------------
00098 // HORIZONTAL DILATION
00099 
00100 void LinDilatedImage::dilateHor(GreyLevelImage* anImg,
00101                                 unsigned int aDilSize)
00102   throw(QgarErrorDomain)
00103 {
00104   int linsize = (2 * aDilSize) + 1;  // Size of dilation segment
00105   int width   = anImg->width();      // Image width & height
00106   int height  = anImg->height();
00107   
00108   if (linsize > width)
00109     {
00110       std::ostringstream os;
00111       os << "Horizontal dilation size ["
00112          << aDilSize
00113          << " -> "
00114          << linsize
00115          << "] too large for image ["
00116          << width
00117          << " X "
00118          << height
00119          << "]";
00120       throw QgarErrorDomain(__FILE__, __LINE__,
00121                             "void qgar::LinDilatedImage::dilateHor(qgar::GreyLevelImage*, unsigned int)",
00122                             os.str());
00123     }
00124   
00125   // Allocate a table for left propagated maximums
00126   GreyLevelImage::value_type* outRow = new GreyLevelImage::value_type [width];
00127   
00128   GreyLevelImage::value_type* pOutRow; // pointer on maximum's table
00129   GreyLevelImage::value_type* inRow;   // pointers on current row
00130   GreyLevelImage::value_type* pInRow;
00131 
00132   int l = 0;   // current line number
00133  
00134   // if width % linsize isn't equal to zero, we have to
00135   // simulate missing pixels at the end of each line
00136 
00137   int overPixels = width % linsize; // pixels in excess
00138 
00139   // and now we can process through each line
00140 
00141   for (; l < height ; l++) {
00142       
00143     GreyLevelImage::value_type maximum = 0; // current local maximum
00144     int firstPixel; // first pixel number in current window
00145     int window; // the window of linsize pixels
00146       
00147     
00148     /*** propagation of maximums to the left ***/
00149     
00150     pInRow = anImg->pRow(l) + width - 1 - overPixels;
00151     pOutRow = outRow + width - 1 - overPixels;
00152     
00153     for ( firstPixel = overPixels; 
00154           firstPixel < width;
00155           firstPixel += linsize)
00156       {
00157 
00158       *pOutRow = *pInRow--;
00159       maximum = *pOutRow--;
00160 
00161       for (window = 1; 
00162            window < linsize ; 
00163            window++, pInRow--) {
00164         if (maximum < *pInRow) maximum = *pInRow;
00165         *pOutRow-- = maximum;
00166       }
00167     }
00168 
00169     // correction of the last overPixels if needed
00170     
00171     if (overPixels) {
00172       
00173       pInRow = anImg->pRow(l) + width - 1;
00174       pOutRow = outRow + width - 1;
00175       *pOutRow = *pInRow--;
00176       maximum = *pOutRow--;
00177       
00178       for ( firstPixel = 1; 
00179             firstPixel < linsize; 
00180             firstPixel++, pInRow--) {
00181         if (maximum < *pInRow) maximum = *pInRow;
00182         *pOutRow-- = maximum;
00183       }
00184     }
00185       
00186 
00187     /*** propagation of maximums to the right, ***/ 
00188     /***   with direct computation of result.  ***/
00189 
00190 
00191     // first sequence:
00192 
00193     // we keep the first aDilSize pixels
00194     pInRow = anImg->pRow(l);
00195     inRow = pInRow + aDilSize;
00196 
00197     pOutRow = outRow;
00198 
00199     for ( firstPixel = 0, maximum = *pInRow; 
00200           firstPixel < (int)aDilSize; 
00201           firstPixel++, pInRow++) {
00202       if (maximum < *pInRow) maximum = *pInRow;
00203     }
00204 
00205     for ( firstPixel++; 
00206           firstPixel < linsize;
00207           firstPixel++, pInRow++) {
00208       if (maximum < *pInRow) maximum = *pInRow;
00209     }
00210 
00211     // the first result...
00212     if (maximum < *pInRow) maximum = *pInRow;
00213     pOutRow++;
00214     pInRow++;
00215     *inRow++ = maximum;
00216            
00217       
00218     // first sequence complete, now we can run the process
00219     for ( ;
00220           firstPixel < width - overPixels;
00221           firstPixel += linsize) {
00222       maximum = *pInRow++;
00223       *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00224       inRow++;
00225       pOutRow++;
00226         
00227       for ( window = 1; 
00228             window < linsize; 
00229             window++, pInRow++, pOutRow++, inRow++){
00230         if (maximum < *pInRow) maximum = *pInRow;
00231         *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00232       }
00233     }
00234       
00235     // we have to do the overPixels...
00236       
00237     if (overPixels) {
00238         
00239       for ( maximum = *pInRow;
00240             firstPixel < width;
00241             firstPixel++, pInRow++, pOutRow++, inRow++) {
00242         if (maximum < *pInRow) maximum = *pInRow;
00243         *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00244       }
00245     }
00246   }
00247   
00248   // Clean up
00249   delete [] outRow;
00250 
00251 }
00252 
00253 // -------------------------------------------------------------------
00254 // VERTICAL DILATION
00255 
00256 void LinDilatedImage::dilateVer(GreyLevelImage* anImg,
00257                                  unsigned int aDilSize)
00258   throw(QgarErrorDomain)
00259 {
00260   int linsize = (2 * aDilSize) + 1;  // Size of dilation segment
00261   int width   = anImg->width();      // Image width & height
00262   int height  = anImg->height();
00263   
00264   if (linsize > height)
00265     {
00266       std::ostringstream os;
00267       os << "Vertical dilation size ["
00268          << aDilSize
00269          << " -> "
00270          << linsize
00271          << "] too large for image ["
00272          << width
00273          << " X "
00274          << height
00275          << "]";
00276       throw QgarErrorDomain(__FILE__, __LINE__,
00277                             "void qgar::LinDilatedImage::dilateVer(qgar::GreyLevelImage*, unsigned int)",
00278                             os.str());
00279     }
00280 
00281   // Allocate a table for left propagated maximums
00282   GreyLevelImage::value_type* outRow = new GreyLevelImage::value_type [height];
00283   
00284   GreyLevelImage::value_type* pOutRow; // pointer on maximum's table
00285   GreyLevelImage::value_type* inRow;   // pointers on current row
00286   GreyLevelImage::value_type* pInRow;
00287 
00288   int l = 0;   // current line number
00289  
00290   // if width % linsize isn't equal to zero, we have to
00291   // simulate missing pixels at the end of each line
00292 
00293   int overPixels = height % linsize; // pixels in excess
00294   
00295   // and now we can process through each line
00296 
00297   for (; l < width ; l++) {
00298       
00299     GreyLevelImage::value_type maximum = 0; // current local maximum
00300     int firstPixel; // first pixel number in current window
00301     int window; // the window of linsize pixels
00302          
00303  
00304     /*** propagation of maximums to the left ***/
00305     
00306     pInRow = anImg->pColumn(l) + width * (height - 1 - overPixels);
00307     pOutRow = outRow + height - 1 - overPixels;
00308     
00309     for ( firstPixel = overPixels; 
00310           firstPixel < height;
00311           firstPixel += linsize) {    
00312 
00313       *pOutRow = *pInRow;
00314       pInRow -= width;
00315       maximum = *pOutRow--;
00316 
00317       for ( window = 1; 
00318             window < linsize; 
00319             window++, pInRow -= width) {
00320         if (maximum < *pInRow) maximum = *pInRow;
00321         *pOutRow-- = maximum;
00322       }
00323     }
00324 
00325     // correction of the last overPixels if needed
00326     
00327     if (overPixels) {
00328       
00329       pInRow = anImg->pColumn(l) + width * (height - 1);
00330       pOutRow = outRow + height - 1;
00331       *pOutRow = *pInRow;
00332       pInRow -= width;
00333       maximum = *pOutRow--;
00334       
00335       for ( firstPixel = 1; 
00336             firstPixel < linsize; 
00337             firstPixel++, pInRow -= width) {
00338         if (maximum < *pInRow) maximum = *pInRow;
00339         *pOutRow-- = maximum;
00340       }
00341     }
00342       
00343     /*** propagation of maximums to the right, ***/ 
00344     /***   with direct computation of result.  ***/
00345     
00346     // first sequence:
00347 
00348     // we keep the first aDilSize pixels
00349     pInRow = anImg->pColumn(l);
00350     inRow = pInRow + aDilSize * width;
00351 
00352     pOutRow = outRow;
00353 
00354     for ( firstPixel = 0, maximum = *pInRow; 
00355           firstPixel < (int)aDilSize; 
00356           firstPixel++, pInRow += width) {
00357       if (maximum < *pInRow) maximum = *pInRow;
00358     }    
00359     
00360     for ( firstPixel++; 
00361           firstPixel < linsize;
00362           firstPixel++, pInRow += width) {
00363       if (maximum < *pInRow) maximum = *pInRow;
00364     }    
00365 
00366     // the first result...
00367     if (maximum < *pInRow) maximum = *pInRow;
00368     pOutRow++;
00369     pInRow += width;
00370     *inRow = maximum;
00371     inRow += width;
00372   
00373     // first sequence complete, now we can run the process
00374     for ( ;
00375           firstPixel < height - overPixels;
00376           firstPixel += linsize) {
00377       
00378       maximum = *pInRow;
00379       pInRow += width;
00380       *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00381       inRow += width;
00382       *pOutRow++;
00383 
00384       for ( window = 1; 
00385             window < linsize; 
00386             window++, pInRow += width, pOutRow++, inRow += width){
00387         if (maximum < *pInRow) maximum = *pInRow;
00388         *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00389       }
00390     }
00391     
00392     // we have to do the overPixels...
00393     
00394     if (overPixels) {
00395 
00396       for ( maximum = *pInRow;
00397             firstPixel < height;
00398             firstPixel++, pInRow += width, pOutRow++, inRow += width) {
00399         if (maximum < *pInRow) maximum = *pInRow;
00400         *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00401       }
00402     }
00403   }
00404 
00405   // Clean up
00406   delete [] outRow;
00407 }
00408 
00409 // -------------------------------------------------------------------
00410 // NE-SW DILATION
00411 
00412 void
00413 LinDilatedImage::dilatePdiag(GreyLevelImage* anImg,
00414                              unsigned int aDilSize)
00415 
00416   throw(QgarErrorDomain)
00417 
00418 {
00419   int linsize = (2 * aDilSize) + 1;  // Size of dilation segment
00420   int width   = anImg->width();      // Image width & height
00421   int height  = anImg->height();
00422   
00423   // Approximative length of the projection of the dilation size
00424   // on one of the coordinate axis
00425   int diagSize = (2 * linsize) / 3;
00426   if ((diagSize > height) || (diagSize > width))
00427     {
00428       std::ostringstream os;
00429       os << "NE-SW dilation size ["
00430          << aDilSize
00431          << " -> "
00432          << linsize
00433          << "] too large for image ["
00434          << width
00435          << " X "
00436          << height
00437          << "]";
00438       throw QgarErrorDomain(__FILE__, __LINE__,
00439                             "void qgar::LinDilatedImage::dilatePDiag(qgar::GreyLevelImage*, unsigned int)",
00440                             os.str());
00441     }
00442   
00443   int i = (width > height ? width : height);
00444 
00445   // Allocate a table for left propagated maximums
00446   GreyLevelImage::value_type* outRow = new GreyLevelImage::value_type [i];
00447 
00448   // Allocate a table for current line
00449   GreyLevelImage::value_type* diagRow = new GreyLevelImage::value_type [i];
00450   
00451   GreyLevelImage::value_type* pOutRow; // pointer on maximum's table
00452 
00453   GreyLevelImage::value_type* inRow;
00454   GreyLevelImage::value_type* pInRow;  // pointers on current row
00455 
00456   // the last line of image
00457   GreyLevelImage::value_type* end = anImg->pRow(height - 1) + 1;
00458 
00459   int l = linsize;   // current line number
00460 
00461   int length; // current line size
00462  
00463   // if width % linsize isn't equal to zero, we have to
00464   // simulate missing pixels at the end of each line
00465 
00466   int overPixels;
00467       
00468   GreyLevelImage::value_type maximum = 0; // current local maximum
00469   int firstPixel; // first pixel number in current window
00470   int window; // the window of linsize pixels
00471 
00472   // and now we can process through each line
00473 
00474   for (; l < height + width - 1 - linsize; l++) {
00475     
00476     if (l < height) {
00477       inRow = anImg->pRow(l);
00478       length = (width > l + 1 ? l + 1 : width);
00479     }
00480     else {
00481       inRow = end;
00482       i = width - l + height - 1;
00483       length = (i > height ? height : i);
00484     }
00485 
00486     pInRow = diagRow;
00487 
00488     // load the current line
00489     for (i = 0 ; i < length; i++) {
00490       *pInRow++ = *inRow;
00491       inRow -= (width - 1);
00492     }
00493 
00494     overPixels = length % linsize; // pixels in excess
00495     
00496     /*** propagation of maximums to the left ***/
00497     
00498     pInRow = diagRow + length - 1 - overPixels;
00499     pOutRow = outRow + length - 1 - overPixels;
00500     
00501     for ( firstPixel = overPixels; 
00502           firstPixel < length;
00503           firstPixel += linsize) {
00504 
00505       *pOutRow = *pInRow--;
00506       maximum = *pOutRow--;
00507 
00508       for (window = 1; 
00509            window < linsize ; 
00510            window++, pInRow--) {
00511         if (maximum < *pInRow) maximum = *pInRow;
00512         *pOutRow-- = maximum;
00513       }
00514     }
00515 
00516     // correction of the last overPixels if needed
00517     
00518     if (overPixels) {
00519       
00520       pInRow = diagRow + length - 1;
00521       pOutRow = outRow + length - 1;
00522       *pOutRow = *pInRow--;
00523       maximum = *pOutRow--;
00524       
00525       for ( firstPixel = 1; 
00526             firstPixel < linsize; 
00527             firstPixel++, pInRow--) {
00528         if (maximum < *pInRow) maximum = *pInRow;
00529         *pOutRow-- = maximum;
00530       }
00531     }
00532       
00533     /*** propagation of maximums to the right, ***/ 
00534     /***   with direct computation of result.  ***/
00535 
00536     // first sequence:
00537 
00538     // we keep the first aDilSize pixels
00539     pInRow = diagRow;
00540     inRow = pInRow + aDilSize;
00541 
00542     pOutRow = outRow;
00543 
00544     for ( firstPixel = 0, maximum = *pInRow; 
00545           firstPixel < (int)aDilSize; 
00546           firstPixel++, pInRow++) {
00547       if (maximum < *pInRow) maximum = *pInRow;
00548     }
00549 
00550     for ( firstPixel++; 
00551           firstPixel < linsize;
00552           firstPixel++, pInRow++) {
00553       if (maximum < *pInRow) maximum = *pInRow;
00554     }
00555 
00556     // the first result...
00557     if (maximum < *pInRow) maximum = *pInRow;
00558     pOutRow++;
00559     pInRow++;
00560     *inRow++ = maximum;
00561            
00562       
00563     // first sequence complete, now we can run the process
00564     for ( ;
00565           firstPixel < length - overPixels;
00566           firstPixel += linsize) {
00567       maximum = *pInRow++;
00568       *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00569       inRow++;
00570       pOutRow++;
00571         
00572       for ( window = 1; 
00573             window < linsize; 
00574             window++, pInRow++, pOutRow++, inRow++){
00575         if (maximum < *pInRow) maximum = *pInRow;
00576         *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00577       }
00578     }
00579       
00580     // we have to do the overPixels...
00581       
00582     if (overPixels) {
00583         
00584       for ( maximum = *pInRow;
00585             firstPixel < length;
00586             firstPixel++, pInRow++, pOutRow++, inRow++) {
00587         if (maximum < *pInRow) maximum = *pInRow;
00588         *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00589       }
00590     }
00591 
00592     // save the current line
00593     if (l < height) inRow = anImg->pRow(l);
00594     else inRow = end++;
00595 
00596     pInRow = diagRow;
00597 
00598     for (i = 0 ; i < length ; i++) {
00599       *inRow = *pInRow++;
00600       inRow -= (width - 1);
00601     }
00602     
00603   }
00604   
00605   // Clean up
00606   delete [] outRow;
00607   delete [] diagRow;
00608 }
00609 
00610 // -------------------------------------------------------------------
00611 // NW-SE DILATION
00612 
00613 void LinDilatedImage::dilateNdiag(GreyLevelImage* anImg,
00614                                  unsigned int aDilSize)
00615 
00616   throw(QgarErrorDomain)
00617 
00618 {
00619   int linsize = (2 * aDilSize) + 1;  // Size of dilation segment
00620   int width   = anImg->width();      // Image width & height
00621   int height  = anImg->height();
00622   
00623   // Approximative length of the projection of the dilation size
00624   // on one of the coordinate axis
00625   int diagSize = (2 * linsize) / 3;
00626   if ((diagSize > height) || (diagSize > width))
00627     {
00628       std::ostringstream os;
00629       os << "NW-SE dilation size ["
00630          << aDilSize
00631          << " -> "
00632          << linsize
00633          << "] too large for image ["
00634          << width
00635          << " X "
00636          << height
00637          << "]";
00638       throw QgarErrorDomain(__FILE__, __LINE__,
00639                             "void qgar::LinDilatedImage::dilateNDiag(qgar::GreyLevelImage*, unsigned int)",
00640                             os.str());
00641     }
00642   
00643   int i = (width > height ? width : height);
00644 
00645   // Allocate a table for left propagated maximums
00646   GreyLevelImage::value_type* outRow = new GreyLevelImage::value_type [i];
00647 
00648   // Allocate a table for current line
00649   GreyLevelImage::value_type* diagRow = new GreyLevelImage::value_type [i];
00650   
00651   GreyLevelImage::value_type* pOutRow; // pointer on maximum's table
00652 
00653   GreyLevelImage::value_type* inRow;
00654   GreyLevelImage::value_type* pInRow;  // pointers on current row
00655 
00656   // the first line of image
00657   GreyLevelImage::value_type* first = anImg->pRow(1) - linsize - 1;
00658 
00659   int l = linsize;   // current line number
00660 
00661   int length; // current line size
00662  
00663   // if width % linsize isn't equal to zero, we have to
00664   // simulate missing pixels at the end of each line
00665 
00666   int overPixels;
00667       
00668   GreyLevelImage::value_type maximum = 0; // current local maximum
00669   int firstPixel; // first pixel number in current window
00670   int window; // the window of linsize pixels
00671 
00672   // and now we can process through each line
00673 
00674   for (; l < height + width - 1 - linsize; l++) {
00675     
00676     if (l < width) {
00677       inRow = first;
00678       length = (l + 1 > height ? height : l + 1);
00679     }
00680     else {
00681       inRow = anImg->pRow(l - width + 1);
00682       i = height - (l - width + 1);
00683       length = (i > width ? width : i);
00684     }
00685 
00686     pInRow = diagRow;
00687 
00688     // load the current line
00689     for (i = 0 ; i < length; i++) {
00690       *pInRow++ = *inRow;
00691       inRow += (width + 1);
00692     }
00693   
00694     overPixels = length % linsize; // pixels in excess
00695       
00696     /*** propagation of maximums to the left ***/
00697     
00698     pInRow = diagRow + length - 1 - overPixels;
00699     pOutRow = outRow + length - 1 - overPixels;
00700     
00701     for ( firstPixel = overPixels; 
00702           firstPixel < length;
00703           firstPixel += linsize) {
00704 
00705       *pOutRow = *pInRow--;
00706       maximum = *pOutRow--;
00707 
00708       for (window = 1; 
00709            window < linsize ; 
00710            window++, pInRow--) {
00711         if (maximum < *pInRow) maximum = *pInRow;
00712         *pOutRow-- = maximum;
00713       }
00714     }
00715 
00716     // correction of the last overPixels if needed
00717     
00718     if (overPixels) {
00719       
00720       pInRow = diagRow + length - 1;
00721       pOutRow = outRow + length - 1;
00722       *pOutRow = *pInRow--;
00723       maximum = *pOutRow--;
00724       
00725       for ( firstPixel = 1; 
00726             firstPixel < linsize; 
00727             firstPixel++, pInRow--) {
00728         if (maximum < *pInRow) maximum = *pInRow;
00729         *pOutRow-- = maximum;
00730       }
00731     }
00732 
00733     /*** propagation of maximums to the right, ***/ 
00734     /***   with direct computation of result.  ***/
00735 
00736     // first sequence:
00737 
00738     // we keep the first aDilSize pixels
00739     pInRow = diagRow;
00740     inRow = pInRow + aDilSize;
00741 
00742     pOutRow = outRow;
00743 
00744     for ( firstPixel = 0, maximum = *pInRow; 
00745           firstPixel < (int)aDilSize; 
00746           firstPixel++, pInRow++) {
00747       if (maximum < *pInRow) maximum = *pInRow;
00748     }
00749 
00750     for ( firstPixel++; 
00751           firstPixel < linsize;
00752           firstPixel++, pInRow++) {
00753       if (maximum < *pInRow) maximum = *pInRow;
00754     }
00755 
00756     // the first result...
00757     if (maximum < *pInRow) maximum = *pInRow;
00758     pOutRow++;
00759     pInRow++;
00760     *inRow++ = maximum;
00761       
00762     // first sequence complete, now we can run the process
00763     for ( ;
00764           firstPixel < length - overPixels;
00765           firstPixel += linsize) {
00766       maximum = *pInRow++;
00767       *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00768       inRow++;
00769       pOutRow++;
00770         
00771       for ( window = 1; 
00772             window < linsize; 
00773             window++, pInRow++, pOutRow++, inRow++){
00774         if (maximum < *pInRow) maximum = *pInRow;
00775         *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00776       }
00777     }
00778       
00779     // we have to do the overPixels...
00780       
00781     if (overPixels) {
00782         
00783       for ( maximum = *pInRow;
00784             firstPixel < length;
00785             firstPixel++, pInRow++, pOutRow++, inRow++) {
00786         if (maximum < *pInRow) maximum = *pInRow;
00787         *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00788       }
00789     }
00790 
00791     // save the current line
00792     
00793     if (l < width) inRow = first--;
00794     else inRow = anImg->pRow(l - width + 1);
00795    
00796     pInRow = diagRow;
00797 
00798     for (i = 0 ; i < length ; i++) {
00799       *inRow = *pInRow++;
00800       inRow += (width + 1);
00801     }
00802 
00803   }
00804 
00805   // Clean up
00806   delete [] outRow;
00807   delete [] diagRow;
00808 }
00809 
00810 // -------------------------------------------------------------------
00811 // ALL-ORIENTATIONS DILATION
00812 
00813 void LinDilatedImage::dilateAll(GreyLevelImage* anImg,
00814                                   unsigned int aDilSize)
00815 
00816   throw(QgarErrorDomain)
00817 
00818 {
00819   int linsize = (2 * aDilSize) + 1;  // Size of dilation segment
00820   int width   = anImg->width();      // Image width & height
00821   int height  = anImg->height();
00822   
00823   // Approximative length of the projection of the dilation size
00824   // on one of the coordinate axis
00825   int diagSize = (2 * linsize) / 3;
00826   if ((diagSize > height) || (diagSize > width))
00827     {
00828       std::ostringstream os;
00829       os << "All-orientations dilation size ["
00830          << aDilSize
00831          << " -> "
00832          << linsize
00833          << "] too large for image ["
00834          << width
00835          << " X "
00836          << height
00837          << "]";
00838       throw QgarErrorDomain(__FILE__, __LINE__,
00839                             "void qgar::LinDilatedImage::dilateAll(qgar::GreyLevelImage*, unsigned int)",
00840                             os.str());
00841     }
00842   
00843   GreyLevelImage work(*anImg);
00844 
00845   // Allocate a table for current input rows
00846   GreyLevelImage::value_type* crow = new GreyLevelImage::value_type [anImg->width() * linsize];
00847 
00848   // Allocate a table for current output row
00849   GreyLevelImage::value_type* orow = new GreyLevelImage::value_type [anImg->width()];
00850   
00851   GreyLevelImage::value_type* p;
00852   GreyLevelImage::value_type* q;
00853   
00854   // Now loop on all possible lines
00855 
00856   int i = 0;   // current line number in input image
00857   int l = aDilSize; // current line number in output image
00858 
00859   for ( ; l < height - (int)aDilSize ; l++, i++)
00860     {
00861       int ii = i; // current line number while loading current rows
00862 
00863       for (q = crow ; ii < i + linsize ; ii++, q += width)
00864         anImg->row(ii, q); // load rows into crow
00865 
00866       int j = aDilSize;
00867       anImg->row(l, orow); // initialize orow with old values
00868       
00869       for (p = orow + aDilSize, q = crow + aDilSize ;
00870            j < width - (int)aDilSize ; j++, q++)
00871         {              // On all columns which can be processed
00872           GreyLevelImage::value_type curhoriz = 0; // start with minimum for all
00873           GreyLevelImage::value_type curverti = 0;
00874           GreyLevelImage::value_type curpdiag = 0;
00875           GreyLevelImage::value_type curndiag = 0;
00876 
00877           GreyLevelImage::value_type* sl = q;
00878           int k = 0;
00879           
00880           for ( ; k < linsize ; k++, sl += width)
00881             {
00882               if (*(sl - aDilSize + k) > curndiag)
00883                 curndiag = *(sl - aDilSize +k);
00884               if (*sl > curverti)
00885                 curverti = *sl;
00886               if (*(sl + (int)aDilSize - k) > curpdiag)
00887                 curpdiag = *(sl + aDilSize - k);
00888               if (k == (int)aDilSize) // if we are on the medium line
00889                 {
00890                   GreyLevelImage::value_type* ssl = sl - aDilSize;
00891                   int kk = 0;
00892                   for ( ; kk < linsize ; kk++, ssl++)
00893                     if (*ssl > curhoriz)
00894                       curhoriz = *ssl;  // found a new maximum
00895                   
00896                 }
00897             }
00898 
00899           // write result
00900           *p++ = std::min(std::min(curndiag, curpdiag), std::min(curhoriz, curverti));
00901         }
00902 
00903       // Write result
00904       work.setRow(l, orow);
00905     }
00906   
00907   for (i = 0; i < height; i++) {
00908     work.row(i, crow);
00909     anImg->setRow(i, crow);
00910   }
00911 
00912   // Clean up
00913   delete [] crow;
00914   delete [] orow;
00915 }
00916 
00917 // -------------------------------------------------------------------
00918 
00919 } // namespace qgar