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

ContrastEnhancedImage.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   ContrastEnhancedImage.C
00030  * @brief  Implementation of class qgar::ContrastEnhancedImage.
00031  *
00032  * See file ContrastEnhancedImage.H for the interface.
00033  *
00034  * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Karl Tombre">Karl Tombre</a>
00035  * @date   July 3, 2001  17:12
00036  * @since  qgar 1.0
00037  */
00038 
00039 
00040 // STL
00041 #include <sstream>
00042 // QGAR
00043 #include <qgarlib/array.H>
00044 #include <qgarlib/ContrastEnhancedImage.H>
00045 #include <qgarlib/GenImage.H>
00046 #include <qgarlib/QgarErrorDomain.H>
00047 
00048 
00049 
00050 namespace qgar
00051 {
00052 
00053 // -------------------------------------------------------------------
00054 // C O N S T R U C T O R
00055 // -------------------------------------------------------------------
00056 ContrastEnhancedImage::ContrastEnhancedImage(GreyLevelImage& anImg,
00057                                              unsigned int aMaskSize)
00058 
00059   throw(QgarErrorDomain)
00060 
00061   : GreyLevelImage(anImg)
00062 
00063 {
00064   int sqsize = (2 * (int)aMaskSize) + 1;  // Effective mask size
00065 
00066   if ((sqsize > _width) || (sqsize > _height))
00067     {
00068       std::ostringstream os;
00069       os << "Mask ["
00070          << sqsize
00071          << " X "
00072          << sqsize
00073          << "] too large for image ["
00074          << _width
00075          << " X "
00076          << _height
00077          << "]";
00078       throw QgarErrorDomain(__FILE__, __LINE__,
00079                             "qgar::ContrastEnhancedImage::ContrastEnhancedImage(qgar::GreyLevelImage&, unsigned int)",
00080                             os.str());
00081     }
00082 
00083   // Allocate a table for the maxima and minima per column
00084   GreyLevelImage::value_type* ltabmax = new GreyLevelImage::value_type[_width];
00085   GreyLevelImage::value_type* ltabmin = new GreyLevelImage::value_type[_width];
00086 
00087   // Allocate a table for current input row
00088   GreyLevelImage::value_type* crow = new GreyLevelImage::value_type[_width];
00089 
00090   // Allocate a table for current output row
00091   GreyLevelImage::value_type* orow = new GreyLevelImage::value_type[_width];
00092   
00093   GreyLevelImage::value_type* p;
00094   GreyLevelImage::value_type* q;
00095   
00096   // Now loop on all lines to process
00097   // As the image was created from anImg, by default the value of the pixels
00098   // is that of anImg, so we do not need to change the first and last rows
00099 
00100   int i = 0; // current line number in input image
00101 
00102   for (int l = (int)aMaskSize ; l < _height - (int)aMaskSize ; ++l, ++i)
00103     {
00104       // Update ltabmax and ltabmin
00105       GreyLevelImage::value_type* smin = ltabmin;
00106       GreyLevelImage::value_type* smax = ltabmax;
00107 
00108       qgFill(ltabmin, _width, (GreyLevelImage::value_type)255);  // Set ltabmin to max value (255)
00109       qgFill(ltabmax, _width, (GreyLevelImage::value_type)  0);  // Set ltabmax to min value (0)
00110   
00111       // ii : current line number while computing ltab
00112       for (int ii = i ; ii < i + sqsize ; ++ii)
00113         {
00114           anImg.row(ii, crow);  // get the current row of anImg
00115           q = crow;
00116           smin = ltabmin;
00117           smax = ltabmax;
00118 
00119           for (int j = 0 ; j < _width ; ++j, ++q, ++smin, ++smax)
00120             {
00121               if (*smax < *q)
00122                 {
00123                   *smax = *q;
00124                 }
00125               if (*smin > *q)
00126                 {
00127                   *smin = *q;
00128                 }
00129             } // END for j
00130         } // END for ii
00131   
00132 
00133       // And now process the current line
00134 
00135       row(l, orow); // initialize with old values
00136       
00137       p = orow + aMaskSize;
00138       q = crow + aMaskSize;
00139       smin = ltabmin, smax = ltabmax;
00140 
00141       for (int j = (int)aMaskSize ;
00142            j < _width - (int)aMaskSize ;
00143            ++j, ++smin, ++smax, ++p, ++q)
00144         {
00145           // On all columns which can be processed
00146           GreyLevelImage::value_type curmax = 0;    // current maximum
00147           GreyLevelImage::value_type curmin = 255;  // current minimum
00148           GreyLevelImage::value_type* slmax = smax;
00149           GreyLevelImage::value_type* slmin = smin;
00150           
00151           for (int k = 0 ; k < sqsize ; ++k, ++slmin, ++slmax)
00152             {
00153               if (curmax < *slmax)
00154                 {
00155                   curmax = *slmax;      // new maximum
00156                 }
00157               if (curmin > *slmin)
00158                 {
00159                   curmin = *slmin;     // new minimum
00160                 }
00161             } // END for k
00162 
00163           // Compute result
00164           if ((curmax - *q) < (*q - curmin))
00165             {
00166               *p = curmax;
00167             }
00168           else
00169             {
00170               *p = curmin;
00171             }
00172         } // END for j
00173 
00174       // Write result
00175       setRow(l, orow);
00176 
00177     } // END for l
00178 
00179   // Clean up
00180   delete [] ltabmin;
00181   delete [] ltabmax;
00182   delete [] crow;
00183   delete [] orow;
00184 }
00185 
00186 // -------------------------------------------------------------------
00187 
00188 } // namespace qgar