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;
66 mColorRampType = other.mColorRampType;
67 mClassificationMode = other.mClassificationMode;
69 mLUTOffset = other.mLUTOffset;
70 mLUTFactor = other.mLUTFactor;
71 mLUTInitialized = other.mLUTInitialized;
73 mColorRampItemList = other.mColorRampItemList;
79 switch ( mColorRampType )
82 return QStringLiteral(
"INTERPOLATED" );
84 return QStringLiteral(
"DISCRETE" );
86 return QStringLiteral(
"EXACT" );
88 return QStringLiteral(
"Unknown" );
93 mColorRampItemList = list.toVector();
95 mLUTInitialized =
false;
106 return mColorRampItemList.isEmpty();
111 if ( type == QLatin1String(
"INTERPOLATED" ) )
115 else if ( type == QLatin1String(
"DISCRETE" ) )
121 mColorRampType =
Exact;
144 QList<double> entryValues;
145 QVector<QColor> entryColors;
155 entryValues.reserve( numberOfEntries );
158 double intervalDiff = max - min;
162 if ( colorGradientRamp && colorGradientRamp->
isDiscrete() )
170 intervalDiff *= ( numberOfEntries - 1 ) / static_cast<double>( numberOfEntries );
174 for (
int i = 1; i < numberOfEntries; ++i )
177 entryValues.push_back( min + value * intervalDiff );
179 entryValues.push_back( std::numeric_limits<double>::infinity() );
183 for (
int i = 0; i < numberOfEntries; ++i )
186 entryValues.push_back( min + value * ( max - min ) );
190 for (
int i = 0; i < numberOfEntries; ++i )
205 if ( band < 0 || !input )
208 double cut1 = std::numeric_limits<double>::quiet_NaN();
209 double cut2 = std::numeric_limits<double>::quiet_NaN();
210 int sampleSize = 250000;
213 input->
cumulativeCut( band, 0.0, 1.0, min, max, extent, sampleSize );
215 entryValues.reserve( classes );
218 double intervalDiff = 1.0 / ( classes );
219 for (
int i = 1; i < classes; ++i )
221 input->
cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
222 entryValues.push_back( cut2 );
224 entryValues.push_back( std::numeric_limits<double>::infinity() );
228 double intervalDiff = 1.0 / ( classes - 1 );
229 for (
int i = 0; i < classes; ++i )
231 input->
cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
232 entryValues.push_back( cut2 );
238 entryValues.reserve( classes );
244 double intervalDiff = ( max - min ) / ( classes );
246 for (
int i = 1; i < classes; ++i )
248 entryValues.push_back( min + i * intervalDiff );
250 entryValues.push_back( std::numeric_limits<double>::infinity() );
255 double intervalDiff = ( max - min ) / ( classes - 1 );
257 for (
int i = 0; i < classes; ++i )
259 entryValues.push_back( min + i * intervalDiff );
270 colorDiff = ( int )( 255 / classes );
273 entryColors.reserve( classes );
274 for (
int i = 0; i < classes; ++i )
278 currentColor.setRgb( colorDiff * idx, 0, 255 - colorDiff * idx );
279 entryColors.push_back( currentColor );
284 entryColors.reserve( classes );
285 for (
int i = 0; i < classes; ++i )
288 entryColors.push_back(
sourceColorRamp()->color( ( (
double ) idx ) / ( classes - 1 ) ) );
293 QList<double>::const_iterator value_it = entryValues.constBegin();
294 QVector<QColor>::const_iterator color_it = entryColors.constBegin();
297 double maxabs = std::log10( std::max( std::fabs( max ), std::fabs( min ) ) );
298 int nDecimals = std::round( std::max( 3.0 + maxabs - std::log10( max - min ), maxabs <= 15.0 ? maxabs + 0.49 : 0.0 ) );
300 QList<QgsColorRampShader::ColorRampItem> colorRampItems;
301 for ( ; value_it != entryValues.constEnd(); ++value_it, ++color_it )
304 newColorRampItem.
value = *value_it;
305 newColorRampItem.
color = *color_it;
306 newColorRampItem.
label = QString::number( *value_it,
'g', nDecimals );
307 colorRampItems.append( newColorRampItem );
310 std::sort( colorRampItems.begin(), colorRampItems.end() );
319 bool QgsColorRampShader::shade(
double value,
int *returnRedValue,
int *returnGreenValue,
int *returnBlueValue,
int *returnAlphaValue )
const 321 if ( mColorRampItemList.isEmpty() )
325 if ( std::isnan( value ) || std::isinf( value ) )
328 int colorRampItemListCount = mColorRampItemList.count();
331 if ( !mLUTInitialized )
338 if ( colorRampItemListCount >= 3 )
340 double rangeValue = colorRampItems[colorRampItemListCount - 2].
value -
minimumValue;
341 if ( rangeValue > 0 )
344 mLUTFactor = ( lutSize - 0.0000001 ) / rangeValue;
347 mLUT.reserve( lutSize );
348 for (
int i = 0; i < lutSize; i++ )
350 val = ( i / mLUTFactor ) + mLUTOffset;
351 while ( idx < colorRampItemListCount
352 && colorRampItems[idx].value - DOUBLE_DIFF_THRESHOLD < val )
356 mLUT.push_back( idx );
360 mLUTInitialized =
true;
365 bool overflow =
false;
368 int lutIndex = ( value - mLUTOffset ) * mLUTFactor;
369 if ( value < mLUTOffset )
373 else if ( lutIndex >= mLUT.count() )
375 idx = colorRampItemListCount - 1;
381 else if ( lutIndex < 0 )
388 idx = mLUT.at( lutIndex );
396 if ( idx >= colorRampItemListCount )
398 idx = colorRampItemListCount - 1;
410 if ( mClip && ( overflow
415 *returnRedValue = currentColorRampItem.
color.red();
416 *returnGreenValue = currentColorRampItem.
color.green();
417 *returnBlueValue = currentColorRampItem.
color.blue();
418 *returnAlphaValue = currentColorRampItem.
color.alpha();
424 float currentRampRange = currentColorRampItem.
value - previousColorRampItem.
value;
425 float offsetInRange = value - previousColorRampItem.
value;
426 float scale = offsetInRange / currentRampRange;
427 const QRgb c1 = previousColorRampItem.
color.rgba();
428 const QRgb c2 = currentColorRampItem.
color.rgba();
430 *returnRedValue = qRed( c1 ) +
static_cast< int >( ( qRed( c2 ) - qRed( c1 ) ) * scale );
431 *returnGreenValue = qGreen( c1 ) +
static_cast< int >( ( qGreen( c2 ) - qGreen( c1 ) ) * scale );
432 *returnBlueValue = qBlue( c1 ) +
static_cast< int >( ( qBlue( c2 ) - qBlue( c1 ) ) * scale );
433 *returnAlphaValue = qAlpha( c1 ) +
static_cast< int >( ( qAlpha( c2 ) - qAlpha( c1 ) ) * scale );
445 *returnRedValue = currentColorRampItem.
color.red();
446 *returnGreenValue = currentColorRampItem.
color.green();
447 *returnBlueValue = currentColorRampItem.
color.blue();
448 *returnAlphaValue = currentColorRampItem.
color.alpha();
456 *returnRedValue = currentColorRampItem.
color.red();
457 *returnGreenValue = currentColorRampItem.
color.green();
458 *returnBlueValue = currentColorRampItem.
color.blue();
459 *returnAlphaValue = currentColorRampItem.
color.alpha();
470 double blueValue,
double alphaValue,
471 int *returnRedValue,
int *returnGreenValue,
472 int *returnBlueValue,
int *returnAlphaValue )
const 474 Q_UNUSED( redValue );
475 Q_UNUSED( greenValue );
476 Q_UNUSED( blueValue );
477 Q_UNUSED( alphaValue );
480 *returnGreenValue = 0;
481 *returnBlueValue = 0;
482 *returnAlphaValue = 0;
489 QVector<QgsColorRampShader::ColorRampItem>::const_iterator colorRampIt = mColorRampItemList.constBegin();
490 for ( ; colorRampIt != mColorRampItemList.constEnd(); ++colorRampIt )
492 symbolItems.push_back( qMakePair( colorRampIt->label, colorRampIt->color ) );
498 QDomElement colorRampShaderElem = doc.createElement( QStringLiteral(
"colorrampshader" ) );
500 colorRampShaderElem.setAttribute( QStringLiteral(
"classificationMode" ),
classificationMode() );
501 colorRampShaderElem.setAttribute( QStringLiteral(
"clip" ),
clip() );
507 colorRampShaderElem.appendChild( colorRampElem );
512 QList<QgsColorRampShader::ColorRampItem>::const_iterator itemIt = itemList.constBegin();
513 for ( ; itemIt != itemList.constEnd(); ++itemIt )
515 QDomElement itemElem = doc.createElement( QStringLiteral(
"item" ) );
516 itemElem.setAttribute( QStringLiteral(
"label" ), itemIt->label );
518 itemElem.setAttribute( QStringLiteral(
"color" ), itemIt->color.name() );
519 itemElem.setAttribute( QStringLiteral(
"alpha" ), itemIt->color.alpha() );
520 colorRampShaderElem.appendChild( itemElem );
522 return colorRampShaderElem;
528 QDomElement sourceColorRampElem = colorRampShaderElem.firstChildElement( QStringLiteral(
"colorramp" ) );
529 if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral(
"name" ) ) == QLatin1String(
"[source]" ) )
534 setColorRampType( colorRampShaderElem.attribute( QStringLiteral(
"colorRampType" ), QStringLiteral(
"INTERPOLATED" ) ) );
535 setClassificationMode( static_cast< QgsColorRampShader::ClassificationMode >( colorRampShaderElem.attribute( QStringLiteral(
"classificationMode" ), QStringLiteral(
"1" ) ).toInt() ) );
536 setClip( colorRampShaderElem.attribute( QStringLiteral(
"clip" ), QStringLiteral(
"0" ) ) == QLatin1String(
"1" ) );
538 QList<QgsColorRampShader::ColorRampItem> itemList;
539 QDomElement itemElem;
544 QDomNodeList itemNodeList = colorRampShaderElem.elementsByTagName( QStringLiteral(
"item" ) );
545 itemList.reserve( itemNodeList.size() );
546 for (
int i = 0; i < itemNodeList.size(); ++i )
548 itemElem = itemNodeList.at( i ).toElement();
549 itemValue = itemElem.attribute( QStringLiteral(
"value" ) ).toDouble();
550 itemLabel = itemElem.attribute( QStringLiteral(
"label" ) );
551 itemColor.setNamedColor( itemElem.attribute( QStringLiteral(
"color" ) ) );
552 itemColor.setAlpha( itemElem.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"255" ) ).toInt() );
ClassificationMode classificationMode() const
Returns the classification mode.
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.
QgsColorRamp * sourceColorRamp() const
Returns the source color ramp.
bool isEmpty() const
Whether the color ramp contains any items.
QDomElement writeXml(QDomDocument &doc) const
Writes configuration to a new DOM element.
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.
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.
QgsColorRampShader & operator=(const QgsColorRampShader &other)
Assignment operator.
QString colorRampTypeAsQString() const
Returns the color ramp type as a string.
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.
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Returns the custom colormap.
void setColorRampType(QgsColorRampShader::Type colorRampType)
Sets the color ramp type.
bool clip() const
Returns whether the shader will clip values which are out of range.
#define QgsDebugMsgLevel(str, level)
double minimumValue() const
Returns the maximum value for the raster shader.
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.
Base class for processing filters like renderers, reprojector, resampler etc.
Type colorRampType() const
Returns the color ramp type.
double maximumValue() const
Returns the minimum value for the raster shader.
void classifyColorRamp(int classes=0, int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
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.
#define DOUBLE_DIFF_THRESHOLD
Interpolates the color between two class breaks linearly.
ClassificationMode
Classification modes used to create the color ramp shader.
Assigns the color of the higher class for every pixel between two class breaks.
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.