QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
qgscolorrampshader.cpp
Go to the documentation of this file.
1 /* **************************************************************************
2  qgscolorrampshader.cpp - description
3  -------------------
4 begin : Fri Dec 28 2007
5 copyright : (C) 2007 by Peter J. Ersts
6 email : [email protected]
7 
8 This class is based off of code that was originally written by Marco Hugentobler and
9 originally part of the larger QgsRasterLayer class
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 // Threshold for treating values as exact match.
22 // Set to 0.0 to support displaying small values (https://github.com/qgis/QGIS/issues/20706)
23 #define DOUBLE_DIFF_THRESHOLD 0.0 // 0.0000001
24 
25 #include "qgslogger.h"
26 #include "qgis.h"
27 #include "qgscolorramp.h"
28 #include "qgscolorrampshader.h"
29 #include "qgsrasterinterface.h"
30 #include "qgsrasterminmaxorigin.h"
31 #include "qgssymbollayerutils.h"
32 
33 #include <cmath>
34 QgsColorRampShader::QgsColorRampShader( double minimumValue, double maximumValue, QgsColorRamp *colorRamp, Type type, ClassificationMode classificationMode )
35  : QgsRasterShaderFunction( minimumValue, maximumValue )
36  , mColorRampType( type )
37  , mClassificationMode( classificationMode )
38 {
39  QgsDebugMsgLevel( QStringLiteral( "called." ), 4 );
40 
41  setSourceColorRamp( colorRamp );
42 }
43 
45  : QgsRasterShaderFunction( other )
46  , mColorRampType( other.mColorRampType )
47  , mClassificationMode( other.mClassificationMode )
48  , mLUT( other.mLUT )
49  , mLUTOffset( other.mLUTOffset )
50  , mLUTFactor( other.mLUTFactor )
51  , mLUTInitialized( other.mLUTInitialized )
52  , mClip( other.mClip )
53 {
54  if ( other.sourceColorRamp() )
55  mSourceColorRamp.reset( other.sourceColorRamp()->clone() );
56  mColorRampItemList = other.mColorRampItemList;
57 }
58 
60 {
61  QgsRasterShaderFunction::operator=( other );
62  if ( other.sourceColorRamp() )
63  mSourceColorRamp.reset( other.sourceColorRamp()->clone() );
64  else
65  mSourceColorRamp.reset();
66 
67  mColorRampType = other.mColorRampType;
68  mClassificationMode = other.mClassificationMode;
69  mLUT = other.mLUT;
70  mLUTOffset = other.mLUTOffset;
71  mLUTFactor = other.mLUTFactor;
72  mLUTInitialized = other.mLUTInitialized;
73  mClip = other.mClip;
74  mColorRampItemList = other.mColorRampItemList;
75  return *this;
76 }
77 
79 {
80  switch ( mColorRampType )
81  {
82  case Interpolated:
83  return QStringLiteral( "INTERPOLATED" );
84  case Discrete:
85  return QStringLiteral( "DISCRETE" );
86  case Exact:
87  return QStringLiteral( "EXACT" );
88  }
89  return QStringLiteral( "Unknown" );
90 }
91 
92 void QgsColorRampShader::setColorRampItemList( const QList<QgsColorRampShader::ColorRampItem> &list )
93 {
94  mColorRampItemList = list.toVector();
95  // Reset the look up table when the color ramp is changed
96  mLUTInitialized = false;
97  mLUT.clear();
98 }
99 
101 {
102  mColorRampType = colorRampType;
103 }
104 
106 {
107  return mColorRampItemList.isEmpty();
108 }
109 
110 void QgsColorRampShader::setColorRampType( const QString &type )
111 {
112  if ( type == QLatin1String( "INTERPOLATED" ) )
113  {
114  mColorRampType = Interpolated;
115  }
116  else if ( type == QLatin1String( "DISCRETE" ) )
117  {
118  mColorRampType = Discrete;
119  }
120  else
121  {
122  mColorRampType = Exact;
123  }
124 }
125 
127 {
128  return mSourceColorRamp.get();
129 }
130 
132 {
133  mSourceColorRamp.reset( colorramp );
134 }
135 
136 void QgsColorRampShader::classifyColorRamp( const int classes, const int band, const QgsRectangle &extent, QgsRasterInterface *input )
137 {
138  if ( minimumValue() >= maximumValue() )
139  {
140  return;
141  }
142 
143  bool discrete = colorRampType() == Discrete;
144 
145  QList<double> entryValues;
146  QVector<QColor> entryColors;
147 
148  double min = minimumValue();
149  double max = maximumValue();
150 
151  if ( classificationMode() == Continuous )
152  {
153  if ( sourceColorRamp() && sourceColorRamp()->count() > 1 )
154  {
155  int numberOfEntries = sourceColorRamp()->count();
156  entryValues.reserve( numberOfEntries );
157  if ( discrete )
158  {
159  double intervalDiff = max - min;
160 
161  // remove last class when ColorRamp is gradient and discrete, as they are implemented with an extra stop
162  QgsGradientColorRamp *colorGradientRamp = dynamic_cast<QgsGradientColorRamp *>( sourceColorRamp() );
163  if ( colorGradientRamp && colorGradientRamp->isDiscrete() )
164  {
165  numberOfEntries--;
166  }
167  else
168  {
169  // if color ramp is continuous scale values to get equally distributed classes.
170  // Doesn't work perfectly when stops are non equally distributed.
171  intervalDiff *= ( numberOfEntries - 1 ) / static_cast<double>( numberOfEntries );
172  }
173 
174  // skip first value (always 0.0)
175  for ( int i = 1; i < numberOfEntries; ++i )
176  {
177  double value = sourceColorRamp()->value( i );
178  entryValues.push_back( min + value * intervalDiff );
179  }
180  entryValues.push_back( std::numeric_limits<double>::infinity() );
181  }
182  else
183  {
184  for ( int i = 0; i < numberOfEntries; ++i )
185  {
186  double value = sourceColorRamp()->value( i );
187  entryValues.push_back( min + value * ( max - min ) );
188  }
189  }
190  // for continuous mode take original color map colors
191  for ( int i = 0; i < numberOfEntries; ++i )
192  {
193  int idx = i;
194  entryColors.push_back( sourceColorRamp()->color( sourceColorRamp()->value( idx ) ) );
195  }
196  }
197  }
198  else // for other classification modes interpolate colors linearly
199  {
200  if ( classes < 2 )
201  return; // < 2 classes is not useful, shouldn't happen, but if it happens save it from crashing
202 
203  if ( classificationMode() == Quantile )
204  {
205  // Quantile
206  if ( band < 0 || !input )
207  return; // quantile classificationr requires a valid band, minMaxOrigin, and input
208 
209  double cut1 = std::numeric_limits<double>::quiet_NaN();
210  double cut2 = std::numeric_limits<double>::quiet_NaN();
211  int sampleSize = 250000;
212 
213  // set min and max from histogram, used later to calculate number of decimals to display
214  input->cumulativeCut( band, 0.0, 1.0, min, max, extent, sampleSize );
215 
216  entryValues.reserve( classes );
217  if ( discrete )
218  {
219  double intervalDiff = 1.0 / ( classes );
220  for ( int i = 1; i < classes; ++i )
221  {
222  input->cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
223  entryValues.push_back( cut2 );
224  }
225  entryValues.push_back( std::numeric_limits<double>::infinity() );
226  }
227  else
228  {
229  double intervalDiff = 1.0 / ( classes - 1 );
230  for ( int i = 0; i < classes; ++i )
231  {
232  input->cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
233  entryValues.push_back( cut2 );
234  }
235  }
236  }
237  else // EqualInterval
238  {
239  entryValues.reserve( classes );
240  if ( discrete )
241  {
242  // in discrete mode the lowest value is not an entry and the highest
243  // value is inf, there are ( numberOfEntries ) of which the first
244  // and last are not used.
245  double intervalDiff = ( max - min ) / ( classes );
246 
247  for ( int i = 1; i < classes; ++i )
248  {
249  entryValues.push_back( min + i * intervalDiff );
250  }
251  entryValues.push_back( std::numeric_limits<double>::infinity() );
252  }
253  else
254  {
255  //because the highest value is also an entry, there are (numberOfEntries - 1) intervals
256  double intervalDiff = ( max - min ) / ( classes - 1 );
257 
258  for ( int i = 0; i < classes; ++i )
259  {
260  entryValues.push_back( min + i * intervalDiff );
261  }
262  }
263  }
264 
265  if ( !sourceColorRamp() || sourceColorRamp()->count() == 1 )
266  {
267  //hard code color range from blue -> red (previous default)
268  int colorDiff = 0;
269  if ( classes != 0 )
270  {
271  colorDiff = ( int )( 255 / classes );
272  }
273 
274  entryColors.reserve( classes );
275  for ( int i = 0; i < classes; ++i )
276  {
277  QColor currentColor;
278  int idx = i;
279  currentColor.setRgb( colorDiff * idx, 0, 255 - colorDiff * idx );
280  entryColors.push_back( currentColor );
281  }
282  }
283  else
284  {
285  entryColors.reserve( classes );
286  for ( int i = 0; i < classes; ++i )
287  {
288  int idx = i;
289  entryColors.push_back( sourceColorRamp()->color( ( ( double ) idx ) / ( classes - 1 ) ) );
290  }
291  }
292  }
293 
294  QList<double>::const_iterator value_it = entryValues.constBegin();
295  QVector<QColor>::const_iterator color_it = entryColors.constBegin();
296 
297  // calculate a reasonable number of decimals to display
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 ) );
300 
301  QList<QgsColorRampShader::ColorRampItem> colorRampItems;
302  for ( ; value_it != entryValues.constEnd(); ++value_it, ++color_it )
303  {
304  QgsColorRampShader::ColorRampItem newColorRampItem;
305  newColorRampItem.value = *value_it;
306  newColorRampItem.color = *color_it;
307  newColorRampItem.label = QString::number( *value_it, 'g', nDecimals );
308  colorRampItems.append( newColorRampItem );
309  }
310 
311  std::sort( colorRampItems.begin(), colorRampItems.end() );
312  setColorRampItemList( colorRampItems );
313 }
314 
315 void QgsColorRampShader::classifyColorRamp( const int band, const QgsRectangle &extent, QgsRasterInterface *input )
316 {
317  classifyColorRamp( colorRampItemList().count(), band, extent, input );
318 }
319 
320 bool QgsColorRampShader::shade( double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue ) const
321 {
322  if ( mColorRampItemList.isEmpty() )
323  {
324  return false;
325  }
326  if ( std::isnan( value ) || std::isinf( value ) )
327  return false;
328 
329  int colorRampItemListCount = mColorRampItemList.count();
330  const QgsColorRampShader::ColorRampItem *colorRampItems = mColorRampItemList.constData();
331  int idx;
332  if ( !mLUTInitialized )
333  {
334  // calculate LUT for faster index recovery
335  mLUTFactor = 1.0;
336  double minimumValue = colorRampItems[0].value;
337  mLUTOffset = minimumValue + DOUBLE_DIFF_THRESHOLD;
338  // Only make lut if at least 3 items, with 2 items the low and high cases handle both
339  if ( colorRampItemListCount >= 3 )
340  {
341  double rangeValue = colorRampItems[colorRampItemListCount - 2].value - minimumValue;
342  if ( rangeValue > 0 )
343  {
344  int lutSize = 256; // TODO: test if speed can be increased with a different LUT size
345  mLUTFactor = ( lutSize - 0.0000001 ) / rangeValue; // decrease slightly to make sure last LUT category is correct
346  idx = 0;
347  double val;
348  mLUT.reserve( lutSize );
349  for ( int i = 0; i < lutSize; i++ )
350  {
351  val = ( i / mLUTFactor ) + mLUTOffset;
352  while ( idx < colorRampItemListCount
353  && colorRampItems[idx].value - DOUBLE_DIFF_THRESHOLD < val )
354  {
355  idx++;
356  }
357  mLUT.push_back( idx );
358  }
359  }
360  }
361  mLUTInitialized = true;
362  }
363 
364  // overflow indicates that value > maximum value + DOUBLE_DIFF_THRESHOLD
365  // that way idx can point to the last valid item
366  bool overflow = false;
367 
368  // find index of the first ColorRampItem that is equal or higher to theValue
369  int lutIndex = ( value - mLUTOffset ) * mLUTFactor;
370  if ( value < mLUTOffset )
371  {
372  idx = 0;
373  }
374  else if ( lutIndex >= mLUT.count() )
375  {
376  idx = colorRampItemListCount - 1;
377  if ( colorRampItems[idx].value + DOUBLE_DIFF_THRESHOLD < value )
378  {
379  overflow = true;
380  }
381  }
382  else if ( lutIndex < 0 )
383  {
384  return false;
385  }
386  else
387  {
388  // get initial value from LUT
389  idx = mLUT.at( lutIndex );
390 
391  // check if it's correct and if not increase until correct
392  // the LUT is made in such a way the index is always correct or too low, never too high
393  while ( idx < colorRampItemListCount && colorRampItems[idx].value + DOUBLE_DIFF_THRESHOLD < value )
394  {
395  idx++;
396  }
397  if ( idx >= colorRampItemListCount )
398  {
399  idx = colorRampItemListCount - 1;
400  overflow = true;
401  }
402  }
403 
404  const QgsColorRampShader::ColorRampItem &currentColorRampItem = colorRampItems[idx];
405 
406  if ( colorRampType() == Interpolated )
407  {
408  // Interpolate the color between two class breaks linearly.
409  if ( idx < 1 || overflow || currentColorRampItem.value - DOUBLE_DIFF_THRESHOLD <= value )
410  {
411  if ( mClip && ( overflow
412  || currentColorRampItem.value - DOUBLE_DIFF_THRESHOLD > value ) )
413  {
414  return false;
415  }
416  *returnRedValue = currentColorRampItem.color.red();
417  *returnGreenValue = currentColorRampItem.color.green();
418  *returnBlueValue = currentColorRampItem.color.blue();
419  *returnAlphaValue = currentColorRampItem.color.alpha();
420  return true;
421  }
422 
423  const QgsColorRampShader::ColorRampItem &previousColorRampItem = colorRampItems[idx - 1];
424 
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();
430 
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 );
435  return true;
436  }
437  else if ( colorRampType() == Discrete )
438  {
439  // Assign the color of the higher class for every pixel between two class breaks.
440  // NOTE: The implementation has always been different than the documentation,
441  // which said lower class before, see https://github.com/qgis/QGIS/issues/22009
442  if ( overflow )
443  {
444  return false;
445  }
446  *returnRedValue = currentColorRampItem.color.red();
447  *returnGreenValue = currentColorRampItem.color.green();
448  *returnBlueValue = currentColorRampItem.color.blue();
449  *returnAlphaValue = currentColorRampItem.color.alpha();
450  return true;
451  }
452  else // EXACT
453  {
454  // Assign the color of the exact matching value in the color ramp item list
455  if ( !overflow && currentColorRampItem.value - DOUBLE_DIFF_THRESHOLD <= value )
456  {
457  *returnRedValue = currentColorRampItem.color.red();
458  *returnGreenValue = currentColorRampItem.color.green();
459  *returnBlueValue = currentColorRampItem.color.blue();
460  *returnAlphaValue = currentColorRampItem.color.alpha();
461  return true;
462  }
463  else
464  {
465  return false;
466  }
467  }
468 }
469 
470 bool QgsColorRampShader::shade( double redValue, double greenValue,
471  double blueValue, double alphaValue,
472  int *returnRedValue, int *returnGreenValue,
473  int *returnBlueValue, int *returnAlphaValue ) const
474 {
475  Q_UNUSED( redValue )
476  Q_UNUSED( greenValue )
477  Q_UNUSED( blueValue )
478  Q_UNUSED( alphaValue )
479 
480  *returnRedValue = 0;
481  *returnGreenValue = 0;
482  *returnBlueValue = 0;
483  *returnAlphaValue = 0;
484 
485  return false;
486 }
487 
488 void QgsColorRampShader::legendSymbologyItems( QList< QPair< QString, QColor > > &symbolItems ) const
489 {
490  QVector<QgsColorRampShader::ColorRampItem>::const_iterator colorRampIt = mColorRampItemList.constBegin();
491  for ( ; colorRampIt != mColorRampItemList.constEnd(); ++colorRampIt )
492  {
493  symbolItems.push_back( qMakePair( colorRampIt->label, colorRampIt->color ) );
494  }
495 }
496 
497 QDomElement QgsColorRampShader::writeXml( QDomDocument &doc ) const
498 {
499  QDomElement colorRampShaderElem = doc.createElement( QStringLiteral( "colorrampshader" ) );
500  colorRampShaderElem.setAttribute( QStringLiteral( "colorRampType" ), colorRampTypeAsQString() );
501  colorRampShaderElem.setAttribute( QStringLiteral( "classificationMode" ), classificationMode() );
502  colorRampShaderElem.setAttribute( QStringLiteral( "clip" ), clip() );
503 
504  // save source color ramp
505  if ( sourceColorRamp() )
506  {
507  QDomElement colorRampElem = QgsSymbolLayerUtils::saveColorRamp( QStringLiteral( "[source]" ), sourceColorRamp(), doc );
508  colorRampShaderElem.appendChild( colorRampElem );
509  }
510 
511  //items
512  QList<QgsColorRampShader::ColorRampItem> itemList = colorRampItemList();
513  QList<QgsColorRampShader::ColorRampItem>::const_iterator itemIt = itemList.constBegin();
514  for ( ; itemIt != itemList.constEnd(); ++itemIt )
515  {
516  QDomElement itemElem = doc.createElement( QStringLiteral( "item" ) );
517  itemElem.setAttribute( QStringLiteral( "label" ), itemIt->label );
518  itemElem.setAttribute( QStringLiteral( "value" ), QgsRasterBlock::printValue( itemIt->value ) );
519  itemElem.setAttribute( QStringLiteral( "color" ), itemIt->color.name() );
520  itemElem.setAttribute( QStringLiteral( "alpha" ), itemIt->color.alpha() );
521  colorRampShaderElem.appendChild( itemElem );
522  }
523  return colorRampShaderElem;
524 }
525 
526 void QgsColorRampShader::readXml( const QDomElement &colorRampShaderElem )
527 {
528  // try to load color ramp (optional)
529  QDomElement sourceColorRampElem = colorRampShaderElem.firstChildElement( QStringLiteral( "colorramp" ) );
530  if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "[source]" ) )
531  {
532  setSourceColorRamp( QgsSymbolLayerUtils::loadColorRamp( sourceColorRampElem ) );
533  }
534 
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" ) );
538 
539  QList<QgsColorRampShader::ColorRampItem> itemList;
540  QDomElement itemElem;
541  QString itemLabel;
542  double itemValue;
543  QColor itemColor;
544 
545  QDomNodeList itemNodeList = colorRampShaderElem.elementsByTagName( QStringLiteral( "item" ) );
546  itemList.reserve( itemNodeList.size() );
547  for ( int i = 0; i < itemNodeList.size(); ++i )
548  {
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() );
554 
555  itemList.push_back( QgsColorRampShader::ColorRampItem( itemValue, itemColor, itemLabel ) );
556  }
557  setColorRampItemList( itemList );
558 }
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.
Definition: qgsrectangle.h:41
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.
Definition: qgscolorramp.h:31
static QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp&#39;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)
Definition: qgslogger.h:39
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...
Definition: qgscolorramp.h:202
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 ...
Definition: qgscolorramp.h:139
QgsColorRampShader(double minimumValue=0.0, double maximumValue=255.0, QgsColorRamp *colorRamp=nullptr, Type type=Interpolated, ClassificationMode classificationMode=Continuous)
Creates a new color ramp shader.