23 #define DOUBLE_DIFF_THRESHOLD 0.0 // 0.0000001 36 , mColorRampType( type )
37 , mClassificationMode( classificationMode )
46 , mColorRampType( other.mColorRampType )
47 , mClassificationMode( other.mClassificationMode )
49 , mLUTOffset( other.mLUTOffset )
50 , mLUTFactor( other.mLUTFactor )
51 , mLUTInitialized( other.mLUTInitialized )
52 , mClip( other.mClip )
56 mColorRampItemList = other.mColorRampItemList;
61 QgsRasterShaderFunction::operator=( other );
67 mColorRampType = other.mColorRampType;
68 mClassificationMode = other.mClassificationMode;
70 mLUTOffset = other.mLUTOffset;
71 mLUTFactor = other.mLUTFactor;
72 mLUTInitialized = other.mLUTInitialized;
74 mColorRampItemList = other.mColorRampItemList;
80 switch ( mColorRampType )
83 return QStringLiteral(
"INTERPOLATED" );
85 return QStringLiteral(
"DISCRETE" );
87 return QStringLiteral(
"EXACT" );
89 return QStringLiteral(
"Unknown" );
94 mColorRampItemList = list.toVector();
96 mLUTInitialized =
false;
107 return mColorRampItemList.isEmpty();
112 if ( type == QLatin1String(
"INTERPOLATED" ) )
116 else if ( type == QLatin1String(
"DISCRETE" ) )
122 mColorRampType =
Exact;
145 QList<double> entryValues;
146 QVector<QColor> entryColors;
156 entryValues.reserve( numberOfEntries );
159 double intervalDiff = max - min;
163 if ( colorGradientRamp && colorGradientRamp->
isDiscrete() )
171 intervalDiff *= ( numberOfEntries - 1 ) / static_cast<double>( numberOfEntries );
175 for (
int i = 1; i < numberOfEntries; ++i )
178 entryValues.push_back( min + value * intervalDiff );
180 entryValues.push_back( std::numeric_limits<double>::infinity() );
184 for (
int i = 0; i < numberOfEntries; ++i )
187 entryValues.push_back( min + value * ( max - min ) );
191 for (
int i = 0; i < numberOfEntries; ++i )
206 if ( band < 0 || !input )
209 double cut1 = std::numeric_limits<double>::quiet_NaN();
210 double cut2 = std::numeric_limits<double>::quiet_NaN();
211 int sampleSize = 250000;
214 input->
cumulativeCut( band, 0.0, 1.0, min, max, extent, sampleSize );
216 entryValues.reserve( classes );
219 double intervalDiff = 1.0 / ( classes );
220 for (
int i = 1; i < classes; ++i )
222 input->
cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
223 entryValues.push_back( cut2 );
225 entryValues.push_back( std::numeric_limits<double>::infinity() );
229 double intervalDiff = 1.0 / ( classes - 1 );
230 for (
int i = 0; i < classes; ++i )
232 input->
cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
233 entryValues.push_back( cut2 );
239 entryValues.reserve( classes );
245 double intervalDiff = ( max - min ) / ( classes );
247 for (
int i = 1; i < classes; ++i )
249 entryValues.push_back( min + i * intervalDiff );
251 entryValues.push_back( std::numeric_limits<double>::infinity() );
256 double intervalDiff = ( max - min ) / ( classes - 1 );
258 for (
int i = 0; i < classes; ++i )
260 entryValues.push_back( min + i * intervalDiff );
271 colorDiff = ( int )( 255 / classes );
274 entryColors.reserve( classes );
275 for (
int i = 0; i < classes; ++i )
279 currentColor.setRgb( colorDiff * idx, 0, 255 - colorDiff * idx );
280 entryColors.push_back( currentColor );
285 entryColors.reserve( classes );
286 for (
int i = 0; i < classes; ++i )
289 entryColors.push_back(
sourceColorRamp()->color( ( (
double ) idx ) / ( classes - 1 ) ) );
294 QList<double>::const_iterator value_it = entryValues.constBegin();
295 QVector<QColor>::const_iterator color_it = entryColors.constBegin();
298 double maxabs = std::log10( std::max( std::fabs( max ), std::fabs( min ) ) );
299 int nDecimals = std::round( std::max( 3.0 + maxabs - std::log10( max - min ), maxabs <= 15.0 ? maxabs + 0.49 : 0.0 ) );
301 QList<QgsColorRampShader::ColorRampItem> colorRampItems;
302 for ( ; value_it != entryValues.constEnd(); ++value_it, ++color_it )
305 newColorRampItem.
value = *value_it;
306 newColorRampItem.
color = *color_it;
307 newColorRampItem.
label = QString::number( *value_it,
'g', nDecimals );
308 colorRampItems.append( newColorRampItem );
311 std::sort( colorRampItems.begin(), colorRampItems.end() );
320 bool QgsColorRampShader::shade(
double value,
int *returnRedValue,
int *returnGreenValue,
int *returnBlueValue,
int *returnAlphaValue )
const 322 if ( mColorRampItemList.isEmpty() )
326 if ( std::isnan( value ) || std::isinf( value ) )
329 int colorRampItemListCount = mColorRampItemList.count();
332 if ( !mLUTInitialized )
339 if ( colorRampItemListCount >= 3 )
341 double rangeValue = colorRampItems[colorRampItemListCount - 2].
value -
minimumValue;
342 if ( rangeValue > 0 )
345 mLUTFactor = ( lutSize - 0.0000001 ) / rangeValue;
348 mLUT.reserve( lutSize );
349 for (
int i = 0; i < lutSize; i++ )
351 val = ( i / mLUTFactor ) + mLUTOffset;
352 while ( idx < colorRampItemListCount
353 && colorRampItems[idx].value - DOUBLE_DIFF_THRESHOLD < val )
357 mLUT.push_back( idx );
361 mLUTInitialized =
true;
366 bool overflow =
false;
369 int lutIndex = ( value - mLUTOffset ) * mLUTFactor;
370 if ( value < mLUTOffset )
374 else if ( lutIndex >= mLUT.count() )
376 idx = colorRampItemListCount - 1;
382 else if ( lutIndex < 0 )
389 idx = mLUT.at( lutIndex );
397 if ( idx >= colorRampItemListCount )
399 idx = colorRampItemListCount - 1;
411 if ( mClip && ( overflow
416 *returnRedValue = currentColorRampItem.
color.red();
417 *returnGreenValue = currentColorRampItem.
color.green();
418 *returnBlueValue = currentColorRampItem.
color.blue();
419 *returnAlphaValue = currentColorRampItem.
color.alpha();
425 float currentRampRange = currentColorRampItem.
value - previousColorRampItem.
value;
426 float offsetInRange = value - previousColorRampItem.
value;
427 float scale = offsetInRange / currentRampRange;
428 const QRgb c1 = previousColorRampItem.
color.rgba();
429 const QRgb c2 = currentColorRampItem.
color.rgba();
431 *returnRedValue = qRed( c1 ) +
static_cast< int >( ( qRed( c2 ) - qRed( c1 ) ) * scale );
432 *returnGreenValue = qGreen( c1 ) +
static_cast< int >( ( qGreen( c2 ) - qGreen( c1 ) ) * scale );
433 *returnBlueValue = qBlue( c1 ) +
static_cast< int >( ( qBlue( c2 ) - qBlue( c1 ) ) * scale );
434 *returnAlphaValue = qAlpha( c1 ) +
static_cast< int >( ( qAlpha( c2 ) - qAlpha( c1 ) ) * scale );
446 *returnRedValue = currentColorRampItem.
color.red();
447 *returnGreenValue = currentColorRampItem.
color.green();
448 *returnBlueValue = currentColorRampItem.
color.blue();
449 *returnAlphaValue = currentColorRampItem.
color.alpha();
457 *returnRedValue = currentColorRampItem.
color.red();
458 *returnGreenValue = currentColorRampItem.
color.green();
459 *returnBlueValue = currentColorRampItem.
color.blue();
460 *returnAlphaValue = currentColorRampItem.
color.alpha();
471 double blueValue,
double alphaValue,
472 int *returnRedValue,
int *returnGreenValue,
473 int *returnBlueValue,
int *returnAlphaValue )
const 476 Q_UNUSED( greenValue )
477 Q_UNUSED( blueValue )
478 Q_UNUSED( alphaValue )
481 *returnGreenValue = 0;
482 *returnBlueValue = 0;
483 *returnAlphaValue = 0;
490 QVector<QgsColorRampShader::ColorRampItem>::const_iterator colorRampIt = mColorRampItemList.constBegin();
491 for ( ; colorRampIt != mColorRampItemList.constEnd(); ++colorRampIt )
493 symbolItems.push_back( qMakePair( colorRampIt->label, colorRampIt->color ) );
499 QDomElement colorRampShaderElem = doc.createElement( QStringLiteral(
"colorrampshader" ) );
501 colorRampShaderElem.setAttribute( QStringLiteral(
"classificationMode" ),
classificationMode() );
502 colorRampShaderElem.setAttribute( QStringLiteral(
"clip" ),
clip() );
508 colorRampShaderElem.appendChild( colorRampElem );
513 QList<QgsColorRampShader::ColorRampItem>::const_iterator itemIt = itemList.constBegin();
514 for ( ; itemIt != itemList.constEnd(); ++itemIt )
516 QDomElement itemElem = doc.createElement( QStringLiteral(
"item" ) );
517 itemElem.setAttribute( QStringLiteral(
"label" ), itemIt->label );
519 itemElem.setAttribute( QStringLiteral(
"color" ), itemIt->color.name() );
520 itemElem.setAttribute( QStringLiteral(
"alpha" ), itemIt->color.alpha() );
521 colorRampShaderElem.appendChild( itemElem );
523 return colorRampShaderElem;
529 QDomElement sourceColorRampElem = colorRampShaderElem.firstChildElement( QStringLiteral(
"colorramp" ) );
530 if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral(
"name" ) ) == QLatin1String(
"[source]" ) )
535 setColorRampType( colorRampShaderElem.attribute( QStringLiteral(
"colorRampType" ), QStringLiteral(
"INTERPOLATED" ) ) );
536 setClassificationMode( static_cast< QgsColorRampShader::ClassificationMode >( colorRampShaderElem.attribute( QStringLiteral(
"classificationMode" ), QStringLiteral(
"1" ) ).toInt() ) );
537 setClip( colorRampShaderElem.attribute( QStringLiteral(
"clip" ), QStringLiteral(
"0" ) ) == QLatin1String(
"1" ) );
539 QList<QgsColorRampShader::ColorRampItem> itemList;
540 QDomElement itemElem;
545 QDomNodeList itemNodeList = colorRampShaderElem.elementsByTagName( QStringLiteral(
"item" ) );
546 itemList.reserve( itemNodeList.size() );
547 for (
int i = 0; i < itemNodeList.size(); ++i )
549 itemElem = itemNodeList.at( i ).toElement();
550 itemValue = itemElem.attribute( QStringLiteral(
"value" ) ).toDouble();
551 itemLabel = itemElem.attribute( QStringLiteral(
"label" ) );
552 itemColor.setNamedColor( itemElem.attribute( QStringLiteral(
"color" ) ) );
553 itemColor.setAlpha( itemElem.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"255" ) ).toInt() );
bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue) const override
Generates and new RGB value based on one input value.
A rectangle specified with double values.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom colormap.
static QString printValue(double value)
Print double value with all necessary significant digits.
Uses quantile (i.e. equal pixel) count.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
virtual QgsColorRamp * clone() const =0
Creates a clone of the color ramp.
QDomElement writeXml(QDomDocument &doc) const
Writes configuration to a new DOM element.
Abstract base class for color ramps.
static QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
QString colorRampTypeAsQString() const
Returns the color ramp type as a string.
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Returns the custom colormap.
QgsColorRampShader & operator=(const QgsColorRampShader &other)
Assignment operator.
double maximumValue() const
Returns the minimum value for the raster shader.
void setClip(bool clip)
Sets whether the shader should not render values out of range.
virtual void cumulativeCut(int bandNo, double lowerCount, double upperCount, double &lowerValue, double &upperValue, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0)
Find values for cumulative pixel count cut.
Type
Supported methods for color interpolation.
void setColorRampType(QgsColorRampShader::Type colorRampType)
Sets the color ramp type.
#define QgsDebugMsgLevel(str, level)
The raster shade function applies a shader to a pixel at render time - typically used to render grays...
virtual double value(int index) const =0
Returns relative value between [0,1] of color at specified index.
void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const override
Returns legend symbology items if provided by renderer.
void readXml(const QDomElement &elem)
Reads configuration from the given DOM element.
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
bool isDiscrete() const
Returns true if the gradient is using discrete interpolation, rather than smoothly interpolating betw...
virtual int count() const =0
Returns number of defined colors, or -1 if undefined.
void setSourceColorRamp(QgsColorRamp *colorramp)
Set the source color ramp.
double minimumValue() const
Returns the maximum value for the raster shader.
Base class for processing filters like renderers, reprojector, resampler etc.
void classifyColorRamp(int classes=0, int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
Type colorRampType() const
Returns the color ramp type.
Assigns the color of the exact matching value in the color ramp item list.
Uses breaks from color palette.
std::unique_ptr< QgsColorRamp > mSourceColorRamp
Source color ramp.
void setClassificationMode(ClassificationMode classificationMode)
Sets classification mode.
bool clip() const
Returns whether the shader will clip values which are out of range.
#define DOUBLE_DIFF_THRESHOLD
Interpolates the color between two class breaks linearly.
ClassificationMode
Classification modes used to create the color ramp shader.
bool isEmpty() const
Whether the color ramp contains any items.
Assigns the color of the higher class for every pixel between two class breaks.
ClassificationMode classificationMode() const
Returns the classification mode.
QgsColorRamp * sourceColorRamp() const
Returns the source color ramp.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
QgsColorRampShader(double minimumValue=0.0, double maximumValue=255.0, QgsColorRamp *colorRamp=nullptr, Type type=Interpolated, ClassificationMode classificationMode=Continuous)
Creates a new color ramp shader.