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