Quantum GIS API Documentation  1.8
src/core/raster/qgscontrastenhancement.cpp
Go to the documentation of this file.
00001 /* **************************************************************************
00002                 qgscontrastenhancement.cpp -  description
00003                        -------------------
00004 begin                : Mon Oct 22 2007
00005 copyright            : (C) 2007 by Peter J. Ersts
00006 email                : ersts@amnh.org
00007 
00008 This class contains code that was originally part of the larger QgsRasterLayer
00009 class originally created circa 2004 by T.Sutton, Gary E.Sherman, Steve Halasz
00010 ****************************************************************************/
00011 
00012 /* **************************************************************************
00013  *                                                                         *
00014  *   This program is free software; you can redistribute it and/or modify  *
00015  *   it under the terms of the GNU General Public License as published by  *
00016  *   the Free Software Foundation; either version 2 of the License, or     *
00017  *   (at your option) any later version.                                   *
00018  *                                                                         *
00019  ***************************************************************************/
00020 
00021 #include "qgslogger.h"
00022 
00023 #include "qgscontrastenhancement.h"
00024 #include "qgscontrastenhancementfunction.h"
00025 #include "qgslinearminmaxenhancement.h"
00026 #include "qgslinearminmaxenhancementwithclip.h"
00027 #include "qgscliptominmaxenhancement.h"
00028 
00029 QgsContrastEnhancement::QgsContrastEnhancement( QgsRasterDataType theDataType )
00030 {
00031   mLookupTable = 0;
00032   mContrastEnhancementFunction = 0;
00033   mEnhancementDirty = false;
00034   mContrastEnhancementAlgorithm = NoEnhancement;
00035   mRasterDataType = theDataType;
00036 
00037   mMinimumValue = minimumValuePossible( mRasterDataType );
00038   mMaximumValue = maximumValuePossible( mRasterDataType );
00039   mRasterDataTypeRange = mMaximumValue - mMinimumValue;
00040 
00041   mLookupTableOffset = mMinimumValue * -1;
00042 
00043   mContrastEnhancementFunction = new QgsContrastEnhancementFunction( mRasterDataType, mMinimumValue, mMaximumValue );
00044 
00045   //If the data type is larger than 16-bit do not generate a lookup table
00046   if ( mRasterDataTypeRange <= 65535.0 )
00047   {
00048     mLookupTable = new int[static_cast <int>( mRasterDataTypeRange+1 )];
00049   }
00050 
00051 }
00052 
00053 QgsContrastEnhancement::~QgsContrastEnhancement()
00054 {
00055 }
00056 /*
00057  *
00058  * Static methods
00059  *
00060  */
00061 
00065 double QgsContrastEnhancement::maximumValuePossible( QgsRasterDataType theDataType )
00066 {
00067   switch ( theDataType )
00068   {
00069     case QGS_Byte:
00070       return std::numeric_limits<unsigned char>::max();
00071       break;
00072     case QGS_UInt16:
00073       return std::numeric_limits<unsigned short>::max();
00074       break;
00075     case QGS_Int16:
00076       return std::numeric_limits<short>::max();
00077       break;
00078     case QGS_UInt32:
00079       return std::numeric_limits<unsigned int>::max();
00080       break;
00081     case QGS_Int32:
00082       return std::numeric_limits<int>::max();
00083       break;
00084     case QGS_Float32:
00085       return std::numeric_limits<float>::max();
00086       break;
00087     case QGS_Float64:
00088       return std::numeric_limits<double>::max();
00089       break;
00090     case QGS_CInt16:
00091       return std::numeric_limits<short>::max();
00092       break;
00093     case QGS_CInt32:
00094       return std::numeric_limits<int>::max();
00095       break;
00096     case QGS_CFloat32:
00097       return std::numeric_limits<float>::max();
00098       break;
00099     case QGS_CFloat64:
00100       return std::numeric_limits<double>::max();
00101       break;
00102     case QGS_Unknown:
00103     case QGS_TypeCount:
00104       // XXX - mloskot: not handled?
00105       break;
00106   }
00107 
00108   return std::numeric_limits<double>::max();
00109 }
00113 double QgsContrastEnhancement::minimumValuePossible( QgsRasterDataType theDataType )
00114 {
00115   switch ( theDataType )
00116   {
00117     case QGS_Byte:
00118       return std::numeric_limits<unsigned char>::min();
00119       break;
00120     case QGS_UInt16:
00121       return std::numeric_limits<unsigned short>::min();
00122       break;
00123     case QGS_Int16:
00124       return std::numeric_limits<short>::min();
00125       break;
00126     case QGS_UInt32:
00127       return std::numeric_limits<unsigned int>::min();
00128       break;
00129     case QGS_Int32:
00130       return std::numeric_limits<int>::min();
00131       break;
00132     case QGS_Float32:
00133       return std::numeric_limits<float>::max() * -1.0;
00134       break;
00135     case QGS_Float64:
00136       return std::numeric_limits<double>::max() * -1.0;
00137       break;
00138     case QGS_CInt16:
00139       return std::numeric_limits<short>::min();
00140       break;
00141     case QGS_CInt32:
00142       return std::numeric_limits<int>::min();
00143       break;
00144     case QGS_CFloat32:
00145       return std::numeric_limits<float>::max() * -1.0;
00146       break;
00147     case QGS_CFloat64:
00148       return std::numeric_limits<double>::max() * -1.0;
00149       break;
00150     case QGS_Unknown:
00151     case QGS_TypeCount:
00152       // XXX - mloskot: not handled?
00153       break;
00154   }
00155 
00156   return std::numeric_limits<double>::max() * -1.0;
00157 }
00158 
00159 /*
00160  *
00161  * Non-Static methods
00162  *
00163  */
00169 int QgsContrastEnhancement::enhanceContrast( double theValue )
00170 {
00171   if ( mEnhancementDirty )
00172   {
00173     generateLookupTable();
00174   }
00175 
00176   if ( mLookupTable && NoEnhancement != mContrastEnhancementAlgorithm )
00177   {
00178     return mLookupTable[static_cast <int>( theValue + mLookupTableOffset )];
00179   }
00180   else
00181   {
00182     // Even if the contrast enhancement algorithms is set to NoEnhancement
00183     // The input values will still have to be scaled for all data types
00184     // greater than 1 byte.
00185     return mContrastEnhancementFunction->enhance( theValue );
00186   }
00187 }
00188 
00192 bool QgsContrastEnhancement::generateLookupTable()
00193 {
00194   mEnhancementDirty = false;
00195 
00196   if ( !mContrastEnhancementFunction )
00197     return false;
00198   if ( NoEnhancement == mContrastEnhancementAlgorithm )
00199     return false;
00200   if ( QGS_Byte != mRasterDataType && QGS_UInt16 != mRasterDataType && QGS_Int16 != mRasterDataType )
00201     return false;
00202   if ( !mLookupTable )
00203     return false;
00204 
00205   QgsDebugMsg( "building lookup table" );
00206   QgsDebugMsg( "***MinimumValue : " + QString::number( mMinimumValue ) );
00207   QgsDebugMsg( "***MaximumValue : " + QString::number( mMaximumValue ) );
00208   QgsDebugMsg( "***mLookupTableOffset : " + QString::number( mLookupTableOffset ) );
00209   QgsDebugMsg( "***mRasterDataTypeRange : " + QString::number( mRasterDataTypeRange ) );
00210 
00211   for ( int myIterator = 0; myIterator <= mRasterDataTypeRange; myIterator++ )
00212   {
00213     mLookupTable[myIterator] = mContrastEnhancementFunction->enhance(( double )myIterator - mLookupTableOffset );
00214   }
00215 
00216   return true;
00217 }
00218 
00224 bool QgsContrastEnhancement::isValueInDisplayableRange( double theValue )
00225 {
00226 
00227   if ( 0 != mContrastEnhancementFunction )
00228   {
00229     return mContrastEnhancementFunction->isValueInDisplayableRange( theValue );
00230   }
00231 
00232   return false;
00233 }
00234 
00241 void QgsContrastEnhancement::setContrastEnhancementAlgorithm( ContrastEnhancementAlgorithm theAlgorithm, bool generateTable )
00242 {
00243   QgsDebugMsg( "called algorithm: " + QString::number(( int )theAlgorithm ) + " generate lookup table: " + QString::number(( int )generateTable ) );
00244 
00245   if ( theAlgorithm != mContrastEnhancementAlgorithm )
00246   {
00247     switch ( theAlgorithm )
00248     {
00249       case StretchToMinimumMaximum :
00250         mContrastEnhancementFunction = new QgsLinearMinMaxEnhancement( mRasterDataType, mMinimumValue, mMaximumValue );
00251         break;
00252       case StretchAndClipToMinimumMaximum :
00253         mContrastEnhancementFunction = new QgsLinearMinMaxEnhancementWithClip( mRasterDataType, mMinimumValue, mMaximumValue );
00254         break;
00255       case ClipToMinimumMaximum :
00256         mContrastEnhancementFunction = new QgsClipToMinMaxEnhancement( mRasterDataType, mMinimumValue, mMaximumValue );
00257         break;
00258       case UserDefinedEnhancement :
00259         //Do nothing
00260         break;
00261       default:
00262         mContrastEnhancementFunction = new QgsContrastEnhancementFunction( mRasterDataType, mMinimumValue, mMaximumValue );
00263         break;
00264     }
00265 
00266     mEnhancementDirty = true;
00267     mContrastEnhancementAlgorithm = theAlgorithm;
00268 
00269     if ( generateTable )
00270     {
00271       generateLookupTable();
00272     }
00273   }
00274 }
00275 
00281 void QgsContrastEnhancement::setContrastEnhancementFunction( QgsContrastEnhancementFunction* theFunction )
00282 {
00283   QgsDebugMsg( "called" );
00284 
00285   if ( 0 != theFunction )
00286   {
00287     mContrastEnhancementFunction = theFunction;
00288     mContrastEnhancementAlgorithm = UserDefinedEnhancement;
00289     generateLookupTable();
00290   }
00291 }
00292 
00299 void QgsContrastEnhancement::setMaximumValue( double theValue, bool generateTable )
00300 {
00301   QgsDebugMsg( "called value: " + QString::number( theValue ) + " generate lookup table: " + QString::number(( int )generateTable ) );
00302 
00303   if ( theValue > maximumValuePossible( mRasterDataType ) )
00304   {
00305     mMaximumValue = maximumValuePossible( mRasterDataType );
00306   }
00307   else
00308   {
00309     mMaximumValue = theValue;
00310   }
00311 
00312   if ( 0 != mContrastEnhancementFunction )
00313   {
00314     mContrastEnhancementFunction->setMaximumValue( theValue );
00315   }
00316 
00317   mEnhancementDirty = true;
00318 
00319   if ( generateTable )
00320   {
00321     generateLookupTable();
00322   }
00323 }
00324 
00331 void QgsContrastEnhancement::setMinimumValue( double theValue, bool generateTable )
00332 {
00333   QgsDebugMsg( "called value: " + QString::number( theValue ) + " generate lookup table: " + QString::number(( int )generateTable ) );
00334 
00335   if ( theValue < minimumValuePossible( mRasterDataType ) )
00336   {
00337     mMinimumValue = minimumValuePossible( mRasterDataType );
00338   }
00339   else
00340   {
00341     mMinimumValue = theValue;
00342   }
00343 
00344   if ( 0 != mContrastEnhancementFunction )
00345   {
00346     mContrastEnhancementFunction->setMinimumValue( theValue );
00347   }
00348 
00349   mEnhancementDirty = true;
00350 
00351   if ( generateTable )
00352   {
00353     generateLookupTable();
00354   }
00355 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines