32#include <QDomDocument>
36using namespace Qt::StringLiterals;
41 , mRasterDataType( dataType )
42 , mRasterDataTypeRange( mMaximumValue - mMinimumValue )
43 , mLookupTableOffset( mMinimumValue * -1 )
45 mContrastEnhancementFunction = std::make_unique<QgsContrastEnhancementFunction>( mRasterDataType, mMinimumValue, mMaximumValue );
48 if ( mRasterDataTypeRange <= 65535.0 )
50 mLookupTable = std::make_unique<int[]>(
static_cast <int>( mRasterDataTypeRange + 1 ) );
55 : mEnhancementDirty( true )
56 , mMinimumValue( ce.mMinimumValue )
57 , mMaximumValue( ce.mMaximumValue )
58 , mRasterDataType( ce.mRasterDataType )
59 , mRasterDataTypeRange( ce.mRasterDataTypeRange )
67 if ( mRasterDataTypeRange <= 65535.0 )
69 mLookupTable = std::make_unique<int[]>(
static_cast <int>( mRasterDataTypeRange + 1 ) );
80 if ( mEnhancementDirty )
82 generateLookupTable();
85 if ( mLookupTable &&
NoEnhancement != mContrastEnhancementAlgorithm )
87 const double shiftedValue = value + mLookupTableOffset;
88 if ( shiftedValue >= 0 && shiftedValue < mRasterDataTypeRange + 1 )
89 return mLookupTable[
static_cast <int>( shiftedValue )];
97 return mContrastEnhancementFunction->enhance( value );
101bool QgsContrastEnhancement::generateLookupTable()
103 mEnhancementDirty =
false;
105 if ( !mContrastEnhancementFunction )
110 switch ( mRasterDataType )
138 QgsDebugMsgLevel( u
"***mLookupTableOffset : %1"_s.arg( mLookupTableOffset ), 4 );
139 QgsDebugMsgLevel( u
"***mRasterDataTypeRange : %1"_s.arg( mRasterDataTypeRange ), 4 );
141 for (
int myIterator = 0; myIterator <= mRasterDataTypeRange; myIterator++ )
143 mLookupTable[myIterator] = mContrastEnhancementFunction->enhance(
static_cast< double >( myIterator ) - mLookupTableOffset );
151 if ( mContrastEnhancementFunction )
153 return mContrastEnhancementFunction->isValueInDisplayableRange( value );
164 mContrastEnhancementFunction = std::make_unique<QgsLinearMinMaxEnhancement>( mRasterDataType, mMinimumValue, mMaximumValue );
167 mContrastEnhancementFunction = std::make_unique<QgsLinearMinMaxEnhancementWithClip>( mRasterDataType, mMinimumValue, mMaximumValue );
170 mContrastEnhancementFunction = std::make_unique<QgsClipToMinMaxEnhancement>( mRasterDataType, mMinimumValue, mMaximumValue );
176 mContrastEnhancementFunction = std::make_unique<QgsContrastEnhancementFunction>( mRasterDataType, mMinimumValue, mMaximumValue );
180 mEnhancementDirty =
true;
181 mContrastEnhancementAlgorithm =
algorithm;
185 generateLookupTable();
195 mContrastEnhancementFunction.reset( function );
197 generateLookupTable();
203 QgsDebugMsgLevel(
"called value: " + QString::number( value ) +
" generate lookup table: " + QString::number(
static_cast< int >( generateTable ) ), 4 );
211 mMaximumValue = value;
214 if ( mContrastEnhancementFunction )
216 mContrastEnhancementFunction->setMaximumValue( value );
219 mEnhancementDirty =
true;
223 generateLookupTable();
229 QgsDebugMsgLevel(
"called value: " + QString::number( value ) +
" generate lookup table: " + QString::number(
static_cast< int >( generateTable ) ), 4 );
237 mMinimumValue = value;
240 if ( mContrastEnhancementFunction )
242 mContrastEnhancementFunction->setMinimumValue( value );
245 mEnhancementDirty =
true;
249 generateLookupTable();
256 QDomElement minElem = doc.createElement( u
"minValue"_s );
258 minElem.appendChild( minText );
259 parentElem.appendChild( minElem );
262 QDomElement maxElem = doc.createElement( u
"maxValue"_s );
264 maxElem.appendChild( maxText );
265 parentElem.appendChild( maxElem );
268 QDomElement algorithmElem = doc.createElement( u
"algorithm"_s );
270 algorithmElem.appendChild( algorithmText );
271 parentElem.appendChild( algorithmElem );
276 const QDomElement minValueElem = elem.firstChildElement( u
"minValue"_s );
277 if ( !minValueElem.isNull() )
279 mMinimumValue = minValueElem.text().toDouble();
281 const QDomElement maxValueElem = elem.firstChildElement( u
"maxValue"_s );
282 if ( !maxValueElem.isNull() )
284 mMaximumValue = maxValueElem.text().toDouble();
286 const QDomElement algorithmElem = elem.firstChildElement( u
"algorithm"_s );
287 if ( !algorithmElem.isNull() )
289 const QString algorithmString = algorithmElem.text();
292 if ( algorithmString ==
"0"_L1 )
296 else if ( algorithmString ==
"1"_L1 )
300 else if ( algorithmString ==
"2"_L1 )
304 else if ( algorithmString ==
"3"_L1 )
308 else if ( algorithmString ==
"4"_L1 )
323 if ( doc.isNull() || element.isNull() )
330 algName = u
"StretchToMinimumMaximum"_s;
335 algName = u
"ClipToMinimumMaximum"_s;
338 algName = u
"ClipToMinimumMaximum"_s;
344 QgsDebugError( u
"No SLD1.0 conversion yet for stretch algorithm %1"_s.arg( algName ) );
351 QDomElement normalizeElem = doc.createElement( u
"sld:Normalize"_s );
352 element.appendChild( normalizeElem );
354 QDomElement vendorOptionAlgorithmElem = doc.createElement( u
"sld:VendorOption"_s );
355 vendorOptionAlgorithmElem.setAttribute( u
"name"_s, u
"algorithm"_s );
356 vendorOptionAlgorithmElem.appendChild( doc.createTextNode( algName ) );
357 normalizeElem.appendChild( vendorOptionAlgorithmElem );
359 QDomElement vendorOptionMinValueElem = doc.createElement( u
"sld:VendorOption"_s );
360 vendorOptionMinValueElem.setAttribute( u
"name"_s, u
"minValue"_s );
361 vendorOptionMinValueElem.appendChild( doc.createTextNode( QString::number(
minimumValue() ) ) );
362 normalizeElem.appendChild( vendorOptionMinValueElem );
364 QDomElement vendorOptionMaxValueElem = doc.createElement( u
"sld:VendorOption"_s );
365 vendorOptionMaxValueElem.setAttribute( u
"name"_s, u
"maxValue"_s );
366 vendorOptionMaxValueElem.appendChild( doc.createTextNode( QString::number(
maximumValue() ) ) );
367 normalizeElem.appendChild( vendorOptionMaxValueElem );
375 return u
"NoEnhancement"_s;
377 return u
"StretchToMinimumMaximum"_s;
379 return u
"StretchAndClipToMinimumMaximum"_s;
381 return u
"ClipToMinimumMaximum"_s;
383 return u
"UserDefinedEnhancement"_s;
385 return u
"NoEnhancement"_s;
390 if ( contrastEnhancementString ==
"StretchToMinimumMaximum"_L1 )
394 else if ( contrastEnhancementString ==
"StretchAndClipToMinimumMaximum"_L1 )
398 else if ( contrastEnhancementString ==
"ClipToMinimumMaximum"_L1 )
402 else if ( contrastEnhancementString ==
"UserDefinedEnhancement"_L1 )
DataType
Raster data types.
@ Float32
Thirty two bit floating point (float).
@ CFloat64
Complex Float64.
@ Int16
Sixteen bit signed integer (qint16).
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30).
@ UInt16
Sixteen bit unsigned integer (quint16).
@ Byte
Eight bit unsigned integer (quint8).
@ UnknownDataType
Unknown or unspecified type.
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
@ Int32
Thirty two bit signed integer (qint32).
@ Float64
Sixty four bit floating point (double).
@ CFloat32
Complex Float32.
@ UInt32
Thirty two bit unsigned integer (quint32).
A contrast enhancement function is the base class for all raster contrast enhancements.
ContrastEnhancementAlgorithm
This enumerator describes the types of contrast enhancement algorithms that can be used.
@ StretchToMinimumMaximum
Linear histogram.
@ StretchAndClipToMinimumMaximum
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
QgsContrastEnhancement(Qgis::DataType datatype=Qgis::DataType::Byte)
Constructor for QgsContrastEnhancement, for the specified data type.
void setMinimumValue(double value, bool generateTable=true)
Sets the minimum value for the contrast enhancement range.
static QString contrastEnhancementAlgorithmString(ContrastEnhancementAlgorithm algorithm)
Returns a string to serialize ContrastEnhancementAlgorithm.
static ContrastEnhancementAlgorithm contrastEnhancementAlgorithmFromString(const QString &contrastEnhancementString)
Deserialize ContrastEnhancementAlgorithm.
static double maximumValuePossible(Qgis::DataType dataType)
Helper function that returns the maximum possible value for a data type.
void setContrastEnhancementAlgorithm(ContrastEnhancementAlgorithm algorithm, bool generateTable=true)
Sets the contrast enhancement algorithm.
bool isValueInDisplayableRange(double value)
Returns true if a pixel value is in displayable range, false if pixel is outside of range (i....
int enhanceContrast(double value)
Applies the contrast enhancement to a value.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const
void readXml(const QDomElement &elem)
double minimumValue() const
Returns the minimum value for the contrast enhancement range.
static double minimumValuePossible(Qgis::DataType dataType)
Helper function that returns the minimum possible value for a data type.
void setContrastEnhancementFunction(QgsContrastEnhancementFunction *function)
Allows the user to set their own custom contrast enhancement function.
void toSld(QDomDocument &doc, QDomElement &element) const
Write ContrastEnhancement tags following SLD v1.0 specs SLD1.0 is limited to the parameters listed in...
~QgsContrastEnhancement()
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
void setMaximumValue(double value, bool generateTable=true)
Sets the maximum value for the contrast enhancement range.
double maximumValue() const
Returns the maximum value for the contrast enhancement range.
static QString printValue(double value, bool localized=false)
Print double value with all necessary significant digits.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)