QGIS API Documentation  2.3.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgscontrastenhancement.cpp
Go to the documentation of this file.
1 /* **************************************************************************
2  qgscontrastenhancement.cpp - description
3  -------------------
4 begin : Mon Oct 22 2007
5 copyright : (C) 2007 by Peter J. Ersts
6 email : ersts@amnh.org
7 
8 This class contains code that was originally part of the larger QgsRasterLayer
9 class originally created circa 2004 by T.Sutton, Gary E.Sherman, Steve Halasz
10 ****************************************************************************/
11 
12 /* **************************************************************************
13  * *
14  * This program is free software; you can redistribute it and/or modify *
15  * it under the terms of the GNU General Public License as published by *
16  * the Free Software Foundation; either version 2 of the License, or *
17  * (at your option) any later version. *
18  * *
19  ***************************************************************************/
20 
21 #include "qgslogger.h"
22 
23 #include "qgscontrastenhancement.h"
28 #include <QDomDocument>
29 #include <QDomElement>
30 
32 {
33  mLookupTable = 0;
35  mEnhancementDirty = false;
37  mRasterDataType = theDataType;
38 
42 
43  mLookupTableOffset = mMinimumValue * -1;
44 
46 
47  //If the data type is larger than 16-bit do not generate a lookup table
48  if ( mRasterDataTypeRange <= 65535.0 )
49  {
50  mLookupTable = new int[static_cast <int>( mRasterDataTypeRange+1 )];
51  }
52 
53 }
54 
56 {
57  mLookupTable = 0;
59  mEnhancementDirty = true;
61 
65 
67 
68  // setContrastEnhancementAlgorithm sets also QgsContrastEnhancementFunction
70 
71  //If the data type is larger than 16-bit do not generate a lookup table
72  if ( mRasterDataTypeRange <= 65535.0 )
73  {
74  mLookupTable = new int[static_cast <int>( mRasterDataTypeRange+1 )];
75  }
76 }
77 
79 {
80  delete [] mLookupTable;
82 }
83 /*
84  *
85  * Static methods
86  *
87  */
88 
93 {
94  switch ( theDataType )
95  {
96  case QGis::Byte:
98  break;
99  case QGis::UInt16:
101  break;
102  case QGis::Int16:
104  break;
105  case QGis::UInt32:
107  break;
108  case QGis::Int32:
110  break;
111  case QGis::Float32:
113  break;
114  case QGis::Float64:
116  break;
117  case QGis::CInt16:
119  break;
120  case QGis::CInt32:
122  break;
123  case QGis::CFloat32:
125  break;
126  case QGis::CFloat64:
128  break;
129  case QGis::ARGB32:
132  // XXX - mloskot: not handled?
133  break;
134  }
135 
137 }
142 {
143  switch ( theDataType )
144  {
145  case QGis::Byte:
147  break;
148  case QGis::UInt16:
150  break;
151  case QGis::Int16:
153  break;
154  case QGis::UInt32:
156  break;
157  case QGis::Int32:
159  break;
160  case QGis::Float32:
161  return std::numeric_limits<float>::max() * -1.0;
162  break;
163  case QGis::Float64:
164  return std::numeric_limits<double>::max() * -1.0;
165  break;
166  case QGis::CInt16:
168  break;
169  case QGis::CInt32:
171  break;
172  case QGis::CFloat32:
173  return std::numeric_limits<float>::max() * -1.0;
174  break;
175  case QGis::CFloat64:
176  return std::numeric_limits<double>::max() * -1.0;
177  break;
178  case QGis::ARGB32:
181  // XXX - mloskot: not handled?
182  break;
183  }
184 
185  return std::numeric_limits<double>::max() * -1.0;
186 }
187 
188 /*
189  *
190  * Non-Static methods
191  *
192  */
199 {
200  if ( mEnhancementDirty )
201  {
203  }
204 
206  {
207  return mLookupTable[static_cast <int>( theValue + mLookupTableOffset )];
208  }
209  else
210  {
211  // Even if the contrast enhancement algorithms is set to NoEnhancement
212  // The input values will still have to be scaled for all data types
213  // greater than 1 byte.
214  return mContrastEnhancementFunction->enhance( theValue );
215  }
216 }
217 
222 {
223  mEnhancementDirty = false;
224 
226  return false;
228  return false;
230  return false;
231  if ( !mLookupTable )
232  return false;
233 
234  QgsDebugMsg( "building lookup table" );
235  QgsDebugMsg( "***MinimumValue : " + QString::number( mMinimumValue ) );
236  QgsDebugMsg( "***MaximumValue : " + QString::number( mMaximumValue ) );
237  QgsDebugMsg( "***mLookupTableOffset : " + QString::number( mLookupTableOffset ) );
238  QgsDebugMsg( "***mRasterDataTypeRange : " + QString::number( mRasterDataTypeRange ) );
239 
240  for ( int myIterator = 0; myIterator <= mRasterDataTypeRange; myIterator++ )
241  {
242  mLookupTable[myIterator] = mContrastEnhancementFunction->enhance(( double )myIterator - mLookupTableOffset );
243  }
244 
245  return true;
246 }
247 
254 {
255 
256  if ( 0 != mContrastEnhancementFunction )
257  {
259  }
260 
261  return false;
262 }
263 
271 {
272  QgsDebugMsg( "called algorithm: " + QString::number(( int )theAlgorithm ) + " generate lookup table: " + QString::number(( int )generateTable ) );
273 
274  if ( theAlgorithm != mContrastEnhancementAlgorithm )
275  {
276  switch ( theAlgorithm )
277  {
280  break;
283  break;
284  case ClipToMinimumMaximum :
286  break;
288  //Do nothing
289  break;
290  default:
292  break;
293  }
294 
295  mEnhancementDirty = true;
296  mContrastEnhancementAlgorithm = theAlgorithm;
297 
298  if ( generateTable )
299  {
301  }
302  }
303 }
304 
311 {
312  QgsDebugMsg( "called" );
313 
314  if ( 0 != theFunction )
315  {
316  mContrastEnhancementFunction = theFunction;
319  }
320 }
321 
328 void QgsContrastEnhancement::setMaximumValue( double theValue, bool generateTable )
329 {
330  QgsDebugMsg( "called value: " + QString::number( theValue ) + " generate lookup table: " + QString::number(( int )generateTable ) );
331 
332  if ( theValue > maximumValuePossible( mRasterDataType ) )
333  {
335  }
336  else
337  {
338  mMaximumValue = theValue;
339  }
340 
341  if ( 0 != mContrastEnhancementFunction )
342  {
344  }
345 
346  mEnhancementDirty = true;
347 
348  if ( generateTable )
349  {
351  }
352 }
353 
360 void QgsContrastEnhancement::setMinimumValue( double theValue, bool generateTable )
361 {
362  QgsDebugMsg( "called value: " + QString::number( theValue ) + " generate lookup table: " + QString::number(( int )generateTable ) );
363 
364  if ( theValue < minimumValuePossible( mRasterDataType ) )
365  {
367  }
368  else
369  {
370  mMinimumValue = theValue;
371  }
372 
373  if ( 0 != mContrastEnhancementFunction )
374  {
376  }
377 
378  mEnhancementDirty = true;
379 
380  if ( generateTable )
381  {
383  }
384 }
385 
386 void QgsContrastEnhancement::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
387 {
388  //minimum value
389  QDomElement minElem = doc.createElement( "minValue" );
390  QDomText minText = doc.createTextNode( QString::number( mMinimumValue ) );
391  minElem.appendChild( minText );
392  parentElem.appendChild( minElem );
393 
394  //maximum value
395  QDomElement maxElem = doc.createElement( "maxValue" );
396  QDomText maxText = doc.createTextNode( QString::number( mMaximumValue ) );
397  maxElem.appendChild( maxText );
398  parentElem.appendChild( maxElem );
399 
400  //algorithm
401  QDomElement algorithmElem = doc.createElement( "algorithm" );
402  QDomText algorithmText = doc.createTextNode( contrastEnhancementAlgorithmString( mContrastEnhancementAlgorithm ) );
403  algorithmElem.appendChild( algorithmText );
404  parentElem.appendChild( algorithmElem );
405 }
406 
407 void QgsContrastEnhancement::readXML( const QDomElement& elem )
408 {
409  QDomElement minValueElem = elem.firstChildElement( "minValue" );
410  if ( !minValueElem.isNull() )
411  {
412  mMinimumValue = minValueElem.text().toDouble();
413  }
414  QDomElement maxValueElem = elem.firstChildElement( "maxValue" );
415  if ( !maxValueElem.isNull() )
416  {
417  mMaximumValue = maxValueElem.text().toDouble();
418  }
419  QDomElement algorithmElem = elem.firstChildElement( "algorithm" );
420  if ( !algorithmElem.isNull() )
421  {
422  QString algorithmString = algorithmElem.text();
424  // old version ( < 19 Apr 2013) was using enum directly -> for backward compatibility
425  if ( algorithmString == "0" )
426  {
427  algorithm = NoEnhancement;
428  }
429  else if ( algorithmString == "1" )
430  {
431  algorithm = StretchToMinimumMaximum;
432  }
433  else if ( algorithmString == "2" )
434  {
435  algorithm = StretchAndClipToMinimumMaximum;
436  }
437  else if ( algorithmString == "3" )
438  {
439  algorithm = ClipToMinimumMaximum;
440  }
441  else if ( algorithmString == "4" )
442  {
443  algorithm = UserDefinedEnhancement;
444  }
445  else
446  {
447  algorithm = contrastEnhancementAlgorithmFromString( algorithmString );
448  }
449 
450  setContrastEnhancementAlgorithm( algorithm );
451  }
452 }
453 
455 {
456  switch ( algorithm )
457  {
458  case NoEnhancement:
459  return "NoEnhancement";
461  return "StretchToMinimumMaximum";
463  return "StretchAndClipToMinimumMaximum";
465  return "ClipToMinimumMaximum";
467  return "UserDefinedEnhancement";
468  }
469  return "NoEnhancement";
470 }
471 
473 {
474  if ( contrastEnhancementString == "StretchToMinimumMaximum" )
475  {
477  }
478  else if ( contrastEnhancementString == "StretchAndClipToMinimumMaximum" )
479  {
481  }
482  else if ( contrastEnhancementString == "ClipToMinimumMaximum" )
483  {
484  return ClipToMinimumMaximum;
485  }
486  else if ( contrastEnhancementString == "UserDefinedEnhancement" )
487  {
488  return UserDefinedEnhancement;
489  }
490  else
491  {
492  return NoEnhancement;
493  }
494 }
void setContrastEnhancementAlgorithm(ContrastEnhancementAlgorithm, bool generateTable=true)
Set the contrast enhancement algorithm.
void writeXML(QDomDocument &doc, QDomElement &parentElem) const
void readXML(const QDomElement &elem)
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
bool isValueInDisplayableRange(double)
Return true if pixel is in stretable range, false if pixel is outside of range (i.e., clipped)
double mLookupTableOffset
Scalar so that values can be used as array indicies.
ContrastEnhancementAlgorithm mContrastEnhancementAlgorithm
Current contrast enhancement algorithm.
static double maximumValuePossible(QGis::DataType)
Helper function that returns the maximum possible value for a GDAL data type.
bool mEnhancementDirty
Flag indicating if the lookup table needs to be regenerated.
bool generateLookupTable()
Method to generate a new lookup table.
int * mLookupTable
Pointer to the lookup table.
double ANALYSIS_EXPORT max(double x, double y)
returns the maximum of two doubles or the first argument if both are equal
void setContrastEnhancementFunction(QgsContrastEnhancementFunction *)
A public method that allows the user to set their own custom contrast enhancment function.
void setMinimumValue(double)
Mutator for the minimum value.
static double minimumValuePossible(QGis::DataType)
Helper function that returns the minimum possible value for a GDAL data type.
double mMaximumValue
user defineable maximum value for the band, used for enhanceContrasting
A linear enhanceContrast enhancement that first clips to min max and then enhanceContrastes linearly ...
void setMinimumValue(double, bool generateTable=true)
Return the minimum value for the contrast enhancement range.
QGis::DataType mRasterDataType
Data type of the band.
static QString contrastEnhancementAlgorithmString(ContrastEnhancementAlgorithm algorithm)
A contrast enhancement funcion is the base class for all raster contrast enhancements.
A color enhancement function that performs a linear enhanceContrast between min and max...
double mRasterDataTypeRange
Maximum range of values for a given data type.
QgsContrastEnhancement(QGis::DataType theDatatype=QGis::Byte)
static ContrastEnhancementAlgorithm contrastEnhancementAlgorithmFromString(const QString &contrastEnhancementString)
ContrastEnhancementAlgorithm
This enumerator describes the types of contrast enhancement algorithms that can be used...
A raster contrast enhancement that will clip a value to the specified min/max range.
int enhanceContrast(double)
Apply the contrast enhancement to a value.
QgsContrastEnhancementFunction * mContrastEnhancementFunction
Pointer to the contrast enhancement function.
DataType
Raster data types.
Definition: qgis.h:204
virtual int enhance(double)
A customizable method that takes in a double and returns a int between 0 and 255. ...
virtual bool isValueInDisplayableRange(double)
A customicable method to indicate if the pixels is displayable.
Manipulates raster pixel values so that they enhanceContrast or clip into a specified numerical range...
double ANALYSIS_EXPORT min(double x, double y)
returns the minimum of two doubles or the first argument if both are equal
double mMinimumValue
User defineable minimum value for the band, used for enhanceContrasting.
void setMaximumValue(double, bool generateTable=true)
Set the maximum value for the contrast enhancement range.
void setMaximumValue(double)
Mustator for the maximum value.