Quantum GIS API Documentation
1.7.4
|
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 ( 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 }