Quantum GIS API Documentation  1.7.4
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                : [email protected]
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 ( 0 == mContrastEnhancementFunction ) { return false; }
00197   if ( NoEnhancement == mContrastEnhancementAlgorithm ) { return false; }
00198   if ( QGS_Byte != mRasterDataType && QGS_UInt16 != mRasterDataType && QGS_Int16 != mRasterDataType ) { return false; }
00199   if ( !mLookupTable ) { return false; }
00200 
00201   QgsDebugMsg( "building lookup table" );
00202   QgsDebugMsg( "***MinimumValue : " + QString::number( mMinimumValue ) );
00203   QgsDebugMsg( "***MaximumValue : " + QString::number( mMaximumValue ) );
00204   QgsDebugMsg( "***mLookupTableOffset : " + QString::number( mLookupTableOffset ) );
00205   QgsDebugMsg( "***mRasterDataTypeRange : " + QString::number( mRasterDataTypeRange ) );
00206 
00207   for ( int myIterator = 0; myIterator <= mRasterDataTypeRange; myIterator++ )
00208   {
00209     mLookupTable[myIterator] = mContrastEnhancementFunction->enhance(( double )myIterator - mLookupTableOffset );
00210   }
00211 
00212   return true;
00213 }
00214 
00220 bool QgsContrastEnhancement::isValueInDisplayableRange( double theValue )
00221 {
00222 
00223   if ( 0 != mContrastEnhancementFunction )
00224   {
00225     return mContrastEnhancementFunction->isValueInDisplayableRange( theValue );
00226   }
00227 
00228   return false;
00229 }
00230 
00237 void QgsContrastEnhancement::setContrastEnhancementAlgorithm( ContrastEnhancementAlgorithm theAlgorithm, bool generateTable )
00238 {
00239   QgsDebugMsg( "called algorithm: " + QString::number(( int )theAlgorithm ) + " generate lookup table: " + QString::number(( int )generateTable ) );
00240 
00241   if ( theAlgorithm != mContrastEnhancementAlgorithm )
00242   {
00243     switch ( theAlgorithm )
00244     {
00245       case StretchToMinimumMaximum :
00246         mContrastEnhancementFunction = new QgsLinearMinMaxEnhancement( mRasterDataType, mMinimumValue, mMaximumValue );
00247         break;
00248       case StretchAndClipToMinimumMaximum :
00249         mContrastEnhancementFunction = new QgsLinearMinMaxEnhancementWithClip( mRasterDataType, mMinimumValue, mMaximumValue );
00250         break;
00251       case ClipToMinimumMaximum :
00252         mContrastEnhancementFunction = new QgsClipToMinMaxEnhancement( mRasterDataType, mMinimumValue, mMaximumValue );
00253         break;
00254       case UserDefinedEnhancement :
00255         //Do nothing
00256         break;
00257       default:
00258         mContrastEnhancementFunction = new QgsContrastEnhancementFunction( mRasterDataType, mMinimumValue, mMaximumValue );
00259         break;
00260     }
00261 
00262     mEnhancementDirty = true;
00263     mContrastEnhancementAlgorithm = theAlgorithm;
00264 
00265     if ( generateTable )
00266     {
00267       generateLookupTable();
00268     }
00269   }
00270 }
00271 
00277 void QgsContrastEnhancement::setContrastEnhancementFunction( QgsContrastEnhancementFunction* theFunction )
00278 {
00279   QgsDebugMsg( "called" );
00280 
00281   if ( 0 != theFunction )
00282   {
00283     mContrastEnhancementFunction = theFunction;
00284     mContrastEnhancementAlgorithm = UserDefinedEnhancement;
00285     generateLookupTable();
00286   }
00287 }
00288 
00295 void QgsContrastEnhancement::setMaximumValue( double theValue, bool generateTable )
00296 {
00297   QgsDebugMsg( "called value: " + QString::number( theValue ) + " generate lookup table: " + QString::number(( int )generateTable ) );
00298 
00299   if ( theValue > maximumValuePossible( mRasterDataType ) )
00300   {
00301     mMaximumValue = maximumValuePossible( mRasterDataType );
00302   }
00303   else
00304   {
00305     mMaximumValue = theValue;
00306   }
00307 
00308   if ( 0 != mContrastEnhancementFunction )
00309   {
00310     mContrastEnhancementFunction->setMaximumValue( theValue );
00311   }
00312 
00313   mEnhancementDirty = true;
00314 
00315   if ( generateTable )
00316   {
00317     generateLookupTable();
00318   }
00319 }
00320 
00327 void QgsContrastEnhancement::setMinimumValue( double theValue, bool generateTable )
00328 {
00329   QgsDebugMsg( "called value: " + QString::number( theValue ) + " generate lookup table: " + QString::number(( int )generateTable ) );
00330 
00331   if ( theValue < minimumValuePossible( mRasterDataType ) )
00332   {
00333     mMinimumValue = minimumValuePossible( mRasterDataType );
00334   }
00335   else
00336   {
00337     mMinimumValue = theValue;
00338   }
00339 
00340   if ( 0 != mContrastEnhancementFunction )
00341   {
00342     mContrastEnhancementFunction->setMinimumValue( theValue );
00343   }
00344 
00345   mEnhancementDirty = true;
00346 
00347   if ( generateTable )
00348   {
00349     generateLookupTable();
00350   }
00351 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines