32#include <QDomDocument>
38 , mRasterDataType( dataType )
39 , mRasterDataTypeRange( mMaximumValue - mMinimumValue )
40 , mLookupTableOffset( mMinimumValue * -1 )
42 mContrastEnhancementFunction = std::make_unique<QgsContrastEnhancementFunction>( mRasterDataType, mMinimumValue, mMaximumValue );
45 if ( mRasterDataTypeRange <= 65535.0 )
47 mLookupTable = std::make_unique<int[]>(
static_cast <int>( mRasterDataTypeRange + 1 ) );
52 : mEnhancementDirty( true )
53 , mMinimumValue( ce.mMinimumValue )
54 , mMaximumValue( ce.mMaximumValue )
55 , mRasterDataType( ce.mRasterDataType )
56 , mRasterDataTypeRange( ce.mRasterDataTypeRange )
64 if ( mRasterDataTypeRange <= 65535.0 )
66 mLookupTable = std::make_unique<int[]>(
static_cast <int>( mRasterDataTypeRange + 1 ) );
77 if ( mEnhancementDirty )
79 generateLookupTable();
82 if ( mLookupTable &&
NoEnhancement != mContrastEnhancementAlgorithm )
84 const double shiftedValue = value + mLookupTableOffset;
85 if ( shiftedValue >= 0 && shiftedValue < mRasterDataTypeRange + 1 )
86 return mLookupTable[
static_cast <int>( shiftedValue )];
94 return mContrastEnhancementFunction->enhance( value );
98bool QgsContrastEnhancement::generateLookupTable()
100 mEnhancementDirty =
false;
102 if ( !mContrastEnhancementFunction )
107 switch ( mRasterDataType )
133 QgsDebugMsgLevel( QStringLiteral(
"***MinimumValue : %1" ).arg( mMinimumValue ), 4 );
134 QgsDebugMsgLevel( QStringLiteral(
"***MaximumValue : %1" ).arg( mMaximumValue ), 4 );
135 QgsDebugMsgLevel( QStringLiteral(
"***mLookupTableOffset : %1" ).arg( mLookupTableOffset ), 4 );
136 QgsDebugMsgLevel( QStringLiteral(
"***mRasterDataTypeRange : %1" ).arg( mRasterDataTypeRange ), 4 );
138 for (
int myIterator = 0; myIterator <= mRasterDataTypeRange; myIterator++ )
140 mLookupTable[myIterator] = mContrastEnhancementFunction->enhance(
static_cast< double >( myIterator ) - mLookupTableOffset );
148 if ( mContrastEnhancementFunction )
150 return mContrastEnhancementFunction->isValueInDisplayableRange( value );
161 mContrastEnhancementFunction = std::make_unique<QgsLinearMinMaxEnhancement>( mRasterDataType, mMinimumValue, mMaximumValue );
164 mContrastEnhancementFunction = std::make_unique<QgsLinearMinMaxEnhancementWithClip>( mRasterDataType, mMinimumValue, mMaximumValue );
167 mContrastEnhancementFunction = std::make_unique<QgsClipToMinMaxEnhancement>( mRasterDataType, mMinimumValue, mMaximumValue );
173 mContrastEnhancementFunction = std::make_unique<QgsContrastEnhancementFunction>( mRasterDataType, mMinimumValue, mMaximumValue );
177 mEnhancementDirty =
true;
178 mContrastEnhancementAlgorithm =
algorithm;
182 generateLookupTable();
192 mContrastEnhancementFunction.reset( function );
194 generateLookupTable();
200 QgsDebugMsgLevel(
"called value: " + QString::number( value ) +
" generate lookup table: " + QString::number(
static_cast< int >( generateTable ) ), 4 );
208 mMaximumValue = value;
211 if ( mContrastEnhancementFunction )
213 mContrastEnhancementFunction->setMaximumValue( value );
216 mEnhancementDirty =
true;
220 generateLookupTable();
226 QgsDebugMsgLevel(
"called value: " + QString::number( value ) +
" generate lookup table: " + QString::number(
static_cast< int >( generateTable ) ), 4 );
234 mMinimumValue = value;
237 if ( mContrastEnhancementFunction )
239 mContrastEnhancementFunction->setMinimumValue( value );
242 mEnhancementDirty =
true;
246 generateLookupTable();
253 QDomElement minElem = doc.createElement( QStringLiteral(
"minValue" ) );
255 minElem.appendChild( minText );
256 parentElem.appendChild( minElem );
259 QDomElement maxElem = doc.createElement( QStringLiteral(
"maxValue" ) );
261 maxElem.appendChild( maxText );
262 parentElem.appendChild( maxElem );
265 QDomElement algorithmElem = doc.createElement( QStringLiteral(
"algorithm" ) );
267 algorithmElem.appendChild( algorithmText );
268 parentElem.appendChild( algorithmElem );
273 const QDomElement minValueElem = elem.firstChildElement( QStringLiteral(
"minValue" ) );
274 if ( !minValueElem.isNull() )
276 mMinimumValue = minValueElem.text().toDouble();
278 const QDomElement maxValueElem = elem.firstChildElement( QStringLiteral(
"maxValue" ) );
279 if ( !maxValueElem.isNull() )
281 mMaximumValue = maxValueElem.text().toDouble();
283 const QDomElement algorithmElem = elem.firstChildElement( QStringLiteral(
"algorithm" ) );
284 if ( !algorithmElem.isNull() )
286 const QString algorithmString = algorithmElem.text();
289 if ( algorithmString == QLatin1String(
"0" ) )
293 else if ( algorithmString == QLatin1String(
"1" ) )
297 else if ( algorithmString == QLatin1String(
"2" ) )
301 else if ( algorithmString == QLatin1String(
"3" ) )
305 else if ( algorithmString == QLatin1String(
"4" ) )
320 if ( doc.isNull() || element.isNull() )
327 algName = QStringLiteral(
"StretchToMinimumMaximum" );
332 algName = QStringLiteral(
"ClipToMinimumMaximum" );
335 algName = QStringLiteral(
"ClipToMinimumMaximum" );
341 QgsDebugError( QStringLiteral(
"No SLD1.0 conversion yet for stretch algorithm %1" ).arg( algName ) );
348 QDomElement normalizeElem = doc.createElement( QStringLiteral(
"sld:Normalize" ) );
349 element.appendChild( normalizeElem );
351 QDomElement vendorOptionAlgorithmElem = doc.createElement( QStringLiteral(
"sld:VendorOption" ) );
352 vendorOptionAlgorithmElem.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"algorithm" ) );
353 vendorOptionAlgorithmElem.appendChild( doc.createTextNode( algName ) );
354 normalizeElem.appendChild( vendorOptionAlgorithmElem );
356 QDomElement vendorOptionMinValueElem = doc.createElement( QStringLiteral(
"sld:VendorOption" ) );
357 vendorOptionMinValueElem.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"minValue" ) );
358 vendorOptionMinValueElem.appendChild( doc.createTextNode( QString::number(
minimumValue() ) ) );
359 normalizeElem.appendChild( vendorOptionMinValueElem );
361 QDomElement vendorOptionMaxValueElem = doc.createElement( QStringLiteral(
"sld:VendorOption" ) );
362 vendorOptionMaxValueElem.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"maxValue" ) );
363 vendorOptionMaxValueElem.appendChild( doc.createTextNode( QString::number(
maximumValue() ) ) );
364 normalizeElem.appendChild( vendorOptionMaxValueElem );
372 return QStringLiteral(
"NoEnhancement" );
374 return QStringLiteral(
"StretchToMinimumMaximum" );
376 return QStringLiteral(
"StretchAndClipToMinimumMaximum" );
378 return QStringLiteral(
"ClipToMinimumMaximum" );
380 return QStringLiteral(
"UserDefinedEnhancement" );
382 return QStringLiteral(
"NoEnhancement" );
387 if ( contrastEnhancementString == QLatin1String(
"StretchToMinimumMaximum" ) )
391 else if ( contrastEnhancementString == QLatin1String(
"StretchAndClipToMinimumMaximum" ) )
395 else if ( contrastEnhancementString == QLatin1String(
"ClipToMinimumMaximum" ) )
399 else if ( contrastEnhancementString == QLatin1String(
"UserDefinedEnhancement" ) )
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)