QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 "qgscolorrampimpl.h"
28 #include "qgscolorrampshader.h"
29 #include "qgsrasterinterface.h"
30 #include "qgsrasterminmaxorigin.h"
31 #include "qgssymbollayerutils.h"
32 #include "qgsreadwritecontext.h"
34 
35 #include <cmath>
36 QgsColorRampShader::QgsColorRampShader( double minimumValue, double maximumValue, QgsColorRamp *colorRamp, Type type, ClassificationMode classificationMode )
37  : QgsRasterShaderFunction( minimumValue, maximumValue )
38  , mColorRampType( type )
39  , mClassificationMode( classificationMode )
40  , mLegendSettings( std::make_unique< QgsColorRampLegendNodeSettings >() )
41 {
42  QgsDebugMsgLevel( QStringLiteral( "called." ), 4 );
43 
44  setSourceColorRamp( colorRamp );
45 }
46 
48 
50  : QgsRasterShaderFunction( other )
51  , mColorRampType( other.mColorRampType )
52  , mClassificationMode( other.mClassificationMode )
53  , mLUT( other.mLUT )
54  , mLUTOffset( other.mLUTOffset )
55  , mLUTFactor( other.mLUTFactor )
56  , mLUTInitialized( other.mLUTInitialized )
57  , mClip( other.mClip )
58  , mLegendSettings( other.legendSettings() ? new QgsColorRampLegendNodeSettings( *other.legendSettings() ) : new QgsColorRampLegendNodeSettings() )
59 {
60  if ( auto *lSourceColorRamp = other.sourceColorRamp() )
61  mSourceColorRamp.reset( lSourceColorRamp->clone() );
62  mColorRampItemList = other.mColorRampItemList;
63 }
64 
66 {
67  QgsRasterShaderFunction::operator=( other );
68  if ( auto *lSourceColorRamp = other.sourceColorRamp() )
69  mSourceColorRamp.reset( lSourceColorRamp->clone() );
70  else
71  mSourceColorRamp.reset();
72 
73  mColorRampType = other.mColorRampType;
74  mClassificationMode = other.mClassificationMode;
75  mLUT = other.mLUT;
76  mLUTOffset = other.mLUTOffset;
77  mLUTFactor = other.mLUTFactor;
78  mLUTInitialized = other.mLUTInitialized;
79  mClip = other.mClip;
80  mColorRampItemList = other.mColorRampItemList;
81  mLegendSettings.reset( other.legendSettings() ? new QgsColorRampLegendNodeSettings( *other.legendSettings() ) : new QgsColorRampLegendNodeSettings() );
82  return *this;
83 }
84 
86 {
87  switch ( mColorRampType )
88  {
89  case Interpolated:
90  return QStringLiteral( "INTERPOLATED" );
91  case Discrete:
92  return QStringLiteral( "DISCRETE" );
93  case Exact:
94  return QStringLiteral( "EXACT" );
95  }
96  return QStringLiteral( "Unknown" );
97 }
98 
99 void QgsColorRampShader::setColorRampItemList( const QList<QgsColorRampShader::ColorRampItem> &list )
100 {
101  mColorRampItemList = list.toVector();
102  // Reset the look up table when the color ramp is changed
103  mLUTInitialized = false;
104  mLUT.clear();
105 }
106 
108 {
109  mColorRampType = colorRampType;
110 }
111 
113 {
114  return mColorRampItemList.isEmpty();
115 }
116 
117 void QgsColorRampShader::setColorRampType( const QString &type )
118 {
119  if ( type == QLatin1String( "INTERPOLATED" ) )
120  {
121  mColorRampType = Interpolated;
122  }
123  else if ( type == QLatin1String( "DISCRETE" ) )
124  {
125  mColorRampType = Discrete;
126  }
127  else
128  {
129  mColorRampType = Exact;
130  }
131 }
132 
134 {
135  return mSourceColorRamp.get();
136 }
137 
139 {
140  std::unique_ptr<QgsGradientColorRamp> ramp = std::make_unique< QgsGradientColorRamp >();
141  const int count = mColorRampItemList.size();
142  if ( count == 0 )
143  {
144  const QColor none( 0, 0, 0, 0 );
145  ramp->setColor1( none );
146  ramp->setColor2( none );
147  }
148  else if ( count == 1 )
149  {
150  ramp->setColor1( mColorRampItemList[0].color );
151  ramp->setColor2( mColorRampItemList[0].color );
152  }
153  else
154  {
155  QgsGradientStopsList stops;
156  // minimum and maximum values can fall outside the range of the item list
157  const double min = minimumValue();
158  const double max = maximumValue();
159  for ( int i = 0; i < count; i++ )
160  {
161  const double offset = ( mColorRampItemList[i].value - min ) / ( max - min );
162  if ( i == 0 )
163  {
164  ramp->setColor1( mColorRampItemList[i].color );
165  if ( offset <= 0.0 )
166  continue;
167  }
168  else if ( i == count - 1 )
169  {
170  ramp->setColor2( mColorRampItemList[i].color );
171  if ( offset >= 1.0 )
172  continue;
173  }
174  stops << QgsGradientStop( offset, mColorRampItemList[i].color );
175  }
176  ramp->setStops( stops );
177  }
178 
179  return ramp.release();
180 }
181 
183 {
184  mSourceColorRamp.reset( colorramp );
185 }
186 
187 void QgsColorRampShader::classifyColorRamp( const int classes, const int band, const QgsRectangle &extent, QgsRasterInterface *input )
188 {
189  if ( minimumValue() > maximumValue() )
190  return;
191 
192  const bool discrete = colorRampType() == Discrete;
193 
194  QList<double> entryValues;
195  QVector<QColor> entryColors;
196 
197  double min = minimumValue();
198  double max = maximumValue();
199 
200  if ( minimumValue() == maximumValue() )
201  {
202  if ( sourceColorRamp() && sourceColorRamp()->count() > 1 )
203  {
204  entryValues.push_back( min );
205  if ( discrete )
206  entryValues.push_back( std::numeric_limits<double>::infinity() );
207  for ( int i = 0; i < entryValues.size(); ++i )
208  entryColors.push_back( sourceColorRamp()->color( sourceColorRamp()->value( i ) ) );
209  }
210  }
211  else if ( classificationMode() == Continuous )
212  {
213  if ( sourceColorRamp() && sourceColorRamp()->count() > 1 )
214  {
215  int numberOfEntries = sourceColorRamp()->count();
216  entryValues.reserve( numberOfEntries );
217  if ( discrete )
218  {
219  double intervalDiff = max - min;
220 
221  // remove last class when ColorRamp is gradient and discrete, as they are implemented with an extra stop
222  QgsGradientColorRamp *colorGradientRamp = dynamic_cast<QgsGradientColorRamp *>( sourceColorRamp() );
223  if ( colorGradientRamp && colorGradientRamp->isDiscrete() )
224  {
225  numberOfEntries--;
226  }
227  else
228  {
229  // if color ramp is continuous scale values to get equally distributed classes.
230  // Doesn't work perfectly when stops are non equally distributed.
231  intervalDiff *= ( numberOfEntries - 1 ) / static_cast<double>( numberOfEntries );
232  }
233 
234  // skip first value (always 0.0)
235  for ( int i = 1; i < numberOfEntries; ++i )
236  {
237  const double value = sourceColorRamp()->value( i );
238  entryValues.push_back( min + value * intervalDiff );
239  }
240  entryValues.push_back( std::numeric_limits<double>::infinity() );
241  }
242  else
243  {
244  for ( int i = 0; i < numberOfEntries; ++i )
245  {
246  const double value = sourceColorRamp()->value( i );
247  entryValues.push_back( min + value * ( max - min ) );
248  }
249  }
250  // for continuous mode take original color map colors
251  for ( int i = 0; i < numberOfEntries; ++i )
252  {
253  const int idx = i;
254  entryColors.push_back( sourceColorRamp()->color( sourceColorRamp()->value( idx ) ) );
255  }
256  }
257  }
258  else // for other classification modes interpolate colors linearly
259  {
260  if ( classes < 2 )
261  return; // < 2 classes is not useful, shouldn't happen, but if it happens save it from crashing
262 
263  if ( classificationMode() == Quantile )
264  {
265  // Quantile
266  if ( band < 0 || !input )
267  return; // quantile classification requires a valid band, minMaxOrigin, and input
268 
269  double cut1 = std::numeric_limits<double>::quiet_NaN();
270  double cut2 = std::numeric_limits<double>::quiet_NaN();
271  // Note: the sample size in other parts of QGIS appears to be 25000, it is ten times here.
272  const int sampleSize = 250000 * 10;
273 
274  // set min and max from histogram, used later to calculate number of decimals to display
275  input->cumulativeCut( band, 0.0, 1.0, min, max, extent, sampleSize );
276 
277  entryValues.reserve( classes );
278  if ( discrete )
279  {
280  const double intervalDiff = 1.0 / ( classes );
281  for ( int i = 1; i < classes; ++i )
282  {
283  input->cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
284  entryValues.push_back( cut2 );
285  }
286  entryValues.push_back( std::numeric_limits<double>::infinity() );
287  }
288  else
289  {
290  const double intervalDiff = 1.0 / ( classes - 1 );
291  for ( int i = 0; i < classes; ++i )
292  {
293  input->cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
294  entryValues.push_back( cut2 );
295  }
296  }
297  }
298  else // EqualInterval
299  {
300  entryValues.reserve( classes );
301  if ( discrete )
302  {
303  // in discrete mode the lowest value is not an entry and the highest
304  // value is inf, there are ( numberOfEntries ) of which the first
305  // and last are not used.
306  const double intervalDiff = ( max - min ) / ( classes );
307 
308  for ( int i = 1; i < classes; ++i )
309  {
310  entryValues.push_back( min + i * intervalDiff );
311  }
312  entryValues.push_back( std::numeric_limits<double>::infinity() );
313  }
314  else
315  {
316  //because the highest value is also an entry, there are (numberOfEntries - 1) intervals
317  const double intervalDiff = ( max - min ) / ( classes - 1 );
318 
319  for ( int i = 0; i < classes; ++i )
320  {
321  entryValues.push_back( min + i * intervalDiff );
322  }
323  }
324  }
325 
326  if ( !sourceColorRamp() || sourceColorRamp()->count() == 1 )
327  {
328  //hard code color range from blue -> red (previous default)
329  int colorDiff = 0;
330  if ( classes != 0 )
331  {
332  colorDiff = ( int )( 255 / classes );
333  }
334 
335  entryColors.reserve( classes );
336  for ( int i = 0; i < classes; ++i )
337  {
338  QColor currentColor;
339  const int idx = i;
340  currentColor.setRgb( colorDiff * idx, 0, 255 - colorDiff * idx );
341  entryColors.push_back( currentColor );
342  }
343  }
344  else
345  {
346  entryColors.reserve( classes );
347  for ( int i = 0; i < classes; ++i )
348  {
349  const int idx = i;
350  entryColors.push_back( sourceColorRamp()->color( ( ( double ) idx ) / ( classes - 1 ) ) );
351  }
352  }
353  }
354 
355  QList<double>::const_iterator value_it = entryValues.constBegin();
356  QVector<QColor>::const_iterator color_it = entryColors.constBegin();
357 
358  // calculate a reasonable number of decimals to display
359  const double maxabs = std::log10( std::max( std::fabs( max ), std::fabs( min ) ) );
360  const int nDecimals = std::round( std::max( 3.0 + maxabs - std::log10( max - min ), maxabs <= 15.0 ? maxabs + 0.49 : 0.0 ) );
361 
362  QList<QgsColorRampShader::ColorRampItem> colorRampItems;
363  for ( ; value_it != entryValues.constEnd(); ++value_it, ++color_it )
364  {
365  QgsColorRampShader::ColorRampItem newColorRampItem;
366  newColorRampItem.value = *value_it;
367  newColorRampItem.color = *color_it;
368  newColorRampItem.label = QString::number( *value_it, 'g', nDecimals );
369  colorRampItems.append( newColorRampItem );
370  }
371 
372  std::sort( colorRampItems.begin(), colorRampItems.end() );
373  setColorRampItemList( colorRampItems );
374 }
375 
376 void QgsColorRampShader::classifyColorRamp( const int band, const QgsRectangle &extent, QgsRasterInterface *input )
377 {
378  classifyColorRamp( colorRampItemList().count(), band, extent, input );
379 }
380 
381 bool QgsColorRampShader::shade( double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue ) const
382 {
383  if ( mColorRampItemList.isEmpty() )
384  {
385  return false;
386  }
387  if ( std::isnan( value ) || std::isinf( value ) )
388  return false;
389 
390  const int colorRampItemListCount = mColorRampItemList.count();
391  const QgsColorRampShader::ColorRampItem *colorRampItems = mColorRampItemList.constData();
392  int idx;
393  if ( !mLUTInitialized )
394  {
395  // calculate LUT for faster index recovery
396  mLUTFactor = 1.0;
397  const double minimumValue = colorRampItems[0].value;
398  mLUTOffset = minimumValue + DOUBLE_DIFF_THRESHOLD;
399  // Only make lut if at least 3 items, with 2 items the low and high cases handle both
400  if ( colorRampItemListCount >= 3 )
401  {
402  const double rangeValue = colorRampItems[colorRampItemListCount - 2].value - minimumValue;
403  if ( rangeValue > 0 )
404  {
405  const int lutSize = 256; // TODO: test if speed can be increased with a different LUT size
406  mLUTFactor = ( lutSize - 0.0000001 ) / rangeValue; // decrease slightly to make sure last LUT category is correct
407  idx = 0;
408  double val;
409  mLUT.reserve( lutSize );
410  for ( int i = 0; i < lutSize; i++ )
411  {
412  val = ( i / mLUTFactor ) + mLUTOffset;
413  while ( idx < colorRampItemListCount
414  && colorRampItems[idx].value - DOUBLE_DIFF_THRESHOLD < val )
415  {
416  idx++;
417  }
418  mLUT.emplace_back( idx );
419  }
420  }
421  }
422  mLUTInitialized = true;
423  }
424 
425  // overflow indicates that value > maximum value + DOUBLE_DIFF_THRESHOLD
426  // that way idx can point to the last valid item
427  bool overflow = false;
428 
429  // find index of the first ColorRampItem that is equal or higher to theValue
430  const int lutIndex = ( value - mLUTOffset ) * mLUTFactor;
431  if ( value <= mLUTOffset )
432  {
433  idx = 0;
434  }
435  else if ( static_cast< std::size_t>( lutIndex ) >= mLUT.size() )
436  {
437  idx = colorRampItemListCount - 1;
438  if ( colorRampItems[idx].value + DOUBLE_DIFF_THRESHOLD < value )
439  {
440  overflow = true;
441  }
442  }
443  else if ( lutIndex < 0 )
444  {
445  return false;
446  }
447  else
448  {
449  // get initial value from LUT
450  idx = mLUT[ lutIndex ];
451 
452  // check if it's correct and if not increase until correct
453  // the LUT is made in such a way the index is always correct or too low, never too high
454  while ( idx < colorRampItemListCount && colorRampItems[idx].value + DOUBLE_DIFF_THRESHOLD < value )
455  {
456  idx++;
457  }
458  if ( idx >= colorRampItemListCount )
459  {
460  idx = colorRampItemListCount - 1;
461  overflow = true;
462  }
463  }
464 
465  const QgsColorRampShader::ColorRampItem &currentColorRampItem = colorRampItems[idx];
466 
467  switch ( colorRampType() )
468  {
469  case Interpolated:
470  {
471  // Interpolate the color between two class breaks linearly.
472  if ( idx < 1 || overflow || currentColorRampItem.value - DOUBLE_DIFF_THRESHOLD <= value )
473  {
474  if ( mClip && ( overflow
475  || currentColorRampItem.value - DOUBLE_DIFF_THRESHOLD > value ) )
476  {
477  return false;
478  }
479  *returnRedValue = currentColorRampItem.color.red();
480  *returnGreenValue = currentColorRampItem.color.green();
481  *returnBlueValue = currentColorRampItem.color.blue();
482  *returnAlphaValue = currentColorRampItem.color.alpha();
483  return true;
484  }
485 
486  const QgsColorRampShader::ColorRampItem &previousColorRampItem = colorRampItems[idx - 1];
487 
488  const float currentRampRange = currentColorRampItem.value - previousColorRampItem.value;
489  const float offsetInRange = value - previousColorRampItem.value;
490  const float scale = offsetInRange / currentRampRange;
491 
492  const QRgb c1 = previousColorRampItem.color.rgba();
493  const QRgb c2 = currentColorRampItem.color.rgba();
494 
495  *returnRedValue = qRed( c1 ) + static_cast< int >( ( qRed( c2 ) - qRed( c1 ) ) * scale );
496  *returnGreenValue = qGreen( c1 ) + static_cast< int >( ( qGreen( c2 ) - qGreen( c1 ) ) * scale );
497  *returnBlueValue = qBlue( c1 ) + static_cast< int >( ( qBlue( c2 ) - qBlue( c1 ) ) * scale );
498  *returnAlphaValue = qAlpha( c1 ) + static_cast< int >( ( qAlpha( c2 ) - qAlpha( c1 ) ) * scale );
499  return true;
500  };
501  case Discrete:
502  {
503  // Assign the color of the higher class for every pixel between two class breaks.
504  // NOTE: The implementation has always been different than the documentation,
505  // which said lower class before, see https://github.com/qgis/QGIS/issues/22009
506  if ( overflow )
507  {
508  return false;
509  }
510  *returnRedValue = currentColorRampItem.color.red();
511  *returnGreenValue = currentColorRampItem.color.green();
512  *returnBlueValue = currentColorRampItem.color.blue();
513  *returnAlphaValue = currentColorRampItem.color.alpha();
514  return true;
515  };
516  case Exact:
517  {
518  // Assign the color of the exact matching value in the color ramp item list
519  if ( !overflow && currentColorRampItem.value - DOUBLE_DIFF_THRESHOLD <= value )
520  {
521  *returnRedValue = currentColorRampItem.color.red();
522  *returnGreenValue = currentColorRampItem.color.green();
523  *returnBlueValue = currentColorRampItem.color.blue();
524  *returnAlphaValue = currentColorRampItem.color.alpha();
525  return true;
526  }
527  else
528  {
529  return false;
530  }
531  }
532  }
533  return false;
534 }
535 
536 bool QgsColorRampShader::shade( double redValue, double greenValue,
537  double blueValue, double alphaValue,
538  int *returnRedValue, int *returnGreenValue,
539  int *returnBlueValue, int *returnAlphaValue ) const
540 {
541  Q_UNUSED( redValue )
542  Q_UNUSED( greenValue )
543  Q_UNUSED( blueValue )
544  Q_UNUSED( alphaValue )
545 
546  *returnRedValue = 0;
547  *returnGreenValue = 0;
548  *returnBlueValue = 0;
549  *returnAlphaValue = 0;
550 
551  return false;
552 }
553 
554 void QgsColorRampShader::legendSymbologyItems( QList< QPair< QString, QColor > > &symbolItems ) const
555 {
556  QVector<QgsColorRampShader::ColorRampItem>::const_iterator colorRampIt = mColorRampItemList.constBegin();
557  for ( ; colorRampIt != mColorRampItemList.constEnd(); ++colorRampIt )
558  {
559  symbolItems.push_back( qMakePair( colorRampIt->label, colorRampIt->color ) );
560  }
561 }
562 
563 QDomElement QgsColorRampShader::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
564 {
565  QDomElement colorRampShaderElem = doc.createElement( QStringLiteral( "colorrampshader" ) );
566  colorRampShaderElem.setAttribute( QStringLiteral( "colorRampType" ), colorRampTypeAsQString() );
567  colorRampShaderElem.setAttribute( QStringLiteral( "classificationMode" ), classificationMode() );
568  colorRampShaderElem.setAttribute( QStringLiteral( "clip" ), clip() );
569  colorRampShaderElem.setAttribute( QStringLiteral( "minimumValue" ), mMinimumValue );
570  colorRampShaderElem.setAttribute( QStringLiteral( "maximumValue" ), mMaximumValue );
571  colorRampShaderElem.setAttribute( QStringLiteral( "labelPrecision" ), mLabelPrecision );
572 
573  // save source color ramp
574  if ( sourceColorRamp() )
575  {
576  const QDomElement colorRampElem = QgsSymbolLayerUtils::saveColorRamp( QStringLiteral( "[source]" ), sourceColorRamp(), doc );
577  colorRampShaderElem.appendChild( colorRampElem );
578  }
579 
580  //items
581  const QList<QgsColorRampShader::ColorRampItem> itemList = colorRampItemList();
582  QList<QgsColorRampShader::ColorRampItem>::const_iterator itemIt = itemList.constBegin();
583  for ( ; itemIt != itemList.constEnd(); ++itemIt )
584  {
585  QDomElement itemElem = doc.createElement( QStringLiteral( "item" ) );
586  itemElem.setAttribute( QStringLiteral( "label" ), itemIt->label );
587  itemElem.setAttribute( QStringLiteral( "value" ), QgsRasterBlock::printValue( itemIt->value ) );
588  itemElem.setAttribute( QStringLiteral( "color" ), itemIt->color.name() );
589  itemElem.setAttribute( QStringLiteral( "alpha" ), itemIt->color.alpha() );
590  colorRampShaderElem.appendChild( itemElem );
591  }
592 
593  if ( mLegendSettings )
594  mLegendSettings->writeXml( doc, colorRampShaderElem, context );
595 
596  return colorRampShaderElem;
597 }
598 
599 void QgsColorRampShader::readXml( const QDomElement &colorRampShaderElem, const QgsReadWriteContext &context )
600 {
601  // try to load color ramp (optional)
602  QDomElement sourceColorRampElem = colorRampShaderElem.firstChildElement( QStringLiteral( "colorramp" ) );
603  if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "[source]" ) )
604  {
605  setSourceColorRamp( QgsSymbolLayerUtils::loadColorRamp( sourceColorRampElem ) );
606  }
607 
608  setColorRampType( colorRampShaderElem.attribute( QStringLiteral( "colorRampType" ), QStringLiteral( "INTERPOLATED" ) ) );
609  setClassificationMode( static_cast< QgsColorRampShader::ClassificationMode >( colorRampShaderElem.attribute( QStringLiteral( "classificationMode" ), QStringLiteral( "1" ) ).toInt() ) );
610  setClip( colorRampShaderElem.attribute( QStringLiteral( "clip" ), QStringLiteral( "0" ) ) == QLatin1String( "1" ) );
611  setMinimumValue( colorRampShaderElem.attribute( QStringLiteral( "minimumValue" ) ).toDouble() );
612  setMaximumValue( colorRampShaderElem.attribute( QStringLiteral( "maximumValue" ) ).toDouble() );
613  setLabelPrecision( colorRampShaderElem.attribute( QStringLiteral( "labelPrecision" ), QStringLiteral( "6" ) ).toDouble() );
614 
615  QList<QgsColorRampShader::ColorRampItem> itemList;
616  QDomElement itemElem;
617  QString itemLabel;
618  double itemValue;
619  QColor itemColor;
620 
621  const QDomNodeList itemNodeList = colorRampShaderElem.elementsByTagName( QStringLiteral( "item" ) );
622  itemList.reserve( itemNodeList.size() );
623  for ( int i = 0; i < itemNodeList.size(); ++i )
624  {
625  itemElem = itemNodeList.at( i ).toElement();
626  itemValue = itemElem.attribute( QStringLiteral( "value" ) ).toDouble();
627  itemLabel = itemElem.attribute( QStringLiteral( "label" ) );
628  itemColor.setNamedColor( itemElem.attribute( QStringLiteral( "color" ) ) );
629  itemColor.setAlpha( itemElem.attribute( QStringLiteral( "alpha" ), QStringLiteral( "255" ) ).toInt() );
630 
631  itemList.push_back( QgsColorRampShader::ColorRampItem( itemValue, itemColor, itemLabel ) );
632  }
633  setColorRampItemList( itemList );
634 
635  if ( !mLegendSettings )
636  mLegendSettings = std::make_unique< QgsColorRampLegendNodeSettings >();
637 
638  mLegendSettings->readXml( colorRampShaderElem, context );
639 }
640 
642 {
643  return mLegendSettings.get();
644 }
645 
647 {
648  if ( settings == mLegendSettings.get() )
649  return;
650  mLegendSettings.reset( settings );
651 }
qgsrasterminmaxorigin.h
QgsColorRamp
Abstract base class for color ramps.
Definition: qgscolorramp.h:29
QgsRasterBlock::printValue
static QString printValue(double value)
Print double value with all necessary significant digits.
Definition: qgsrasterblock.cpp:618
qgscolorrampimpl.h
QgsColorRampShader::setSourceColorRamp
void setSourceColorRamp(QgsColorRamp *colorramp)
Set the source color ramp.
Definition: qgscolorrampshader.cpp:182
QgsGradientColorRamp
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Definition: qgscolorrampimpl.h:136
QgsColorRampShader::setClassificationMode
void setClassificationMode(ClassificationMode classificationMode)
Sets classification mode.
Definition: qgscolorrampshader.h:216
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:34
QgsColorRampShader::~QgsColorRampShader
~QgsColorRampShader() override
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsRasterInterface::cumulativeCut
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.
Definition: qgsrasterinterface.cpp:523
qgsreadwritecontext.h
QgsColorRampShader::isEmpty
bool isEmpty() const
Whether the color ramp contains any items.
Definition: qgscolorrampshader.cpp:112
qgssymbollayerutils.h
QgsColorRampShader::classifyColorRamp
void classifyColorRamp(int classes=0, int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
Definition: qgscolorrampshader.cpp:187
QgsRasterShaderFunction::maximumValue
double maximumValue() const
Returns the minimum value for the raster shader.
Definition: qgsrastershaderfunction.h:119
qgis.h
qgscolorrampshader.h
QgsRasterShaderFunction::mMinimumValue
double mMinimumValue
User defineable minimum value for the shading function.
Definition: qgsrastershaderfunction.h:143
QgsColorRampShader
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
Definition: qgscolorrampshader.h:42
QgsColorRampShader::Type
Type
Supported methods for color interpolation.
Definition: qgscolorrampshader.h:48
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsColorRampShader::colorRampTypeAsQString
QString colorRampTypeAsQString() const
Returns the color ramp type as a string.
Definition: qgscolorrampshader.cpp:85
QgsColorRampShader::Quantile
@ Quantile
Uses quantile (i.e. equal pixel) count.
Definition: qgscolorrampshader.h:60
QgsColorRampShader::Discrete
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
Definition: qgscolorrampshader.h:51
QgsColorRampShader::createColorRamp
QgsColorRamp * createColorRamp() const
Creates a gradient color ramp from shader settings.
Definition: qgscolorrampshader.cpp:138
QgsColorRampShader::ColorRampItem::color
QColor color
Definition: qgscolorrampshader.h:118
qgsrasterinterface.h
QgsColorRampShader::setColorRampType
void setColorRampType(QgsColorRampShader::Type colorRampType)
Sets the color ramp type.
Definition: qgscolorrampshader.cpp:107
QgsRasterShaderFunction::setLabelPrecision
void setLabelPrecision(int labelPrecision)
Sets label precision to labelPrecision.
Definition: qgsrastershaderfunction.cpp:79
QgsColorRampShader::Continuous
@ Continuous
Uses breaks from color palette.
Definition: qgscolorrampshader.h:58
QgsColorRampShader::sourceColorRamp
QgsColorRamp * sourceColorRamp() const
Returns the source color ramp.
Definition: qgscolorrampshader.cpp:133
QgsColorRampShader::setClip
void setClip(bool clip)
Sets whether the shader should not render values out of range.
Definition: qgscolorrampshader.h:226
QgsColorRampShader::ColorRampItem
Definition: qgscolorrampshader.h:105
QgsColorRampShader::legendSymbologyItems
void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const override
Returns legend symbology items if provided by renderer.
Definition: qgscolorrampshader.cpp:554
QgsColorRampShader::Exact
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
Definition: qgscolorrampshader.h:52
QgsColorRampShader::writeXml
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context=QgsReadWriteContext()) const
Writes configuration to a new DOM element.
Definition: qgscolorrampshader.cpp:563
QgsColorRampShader::QgsColorRampShader
QgsColorRampShader(double minimumValue=0.0, double maximumValue=255.0, QgsColorRamp *colorRamp=nullptr, Type type=Interpolated, ClassificationMode classificationMode=Continuous)
Creates a new color ramp shader.
Definition: qgscolorrampshader.cpp:36
QgsSymbolLayerUtils::saveColorRamp
static QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
Definition: qgssymbollayerutils.cpp:3355
QgsRasterShaderFunction::setMaximumValue
virtual void setMaximumValue(double value)
Sets the maximum value for the raster shader.
Definition: qgsrastershaderfunction.cpp:30
QgsRasterShaderFunction::mMaximumValue
double mMaximumValue
User defineable maximum value for the shading function.
Definition: qgsrastershaderfunction.h:140
DOUBLE_DIFF_THRESHOLD
#define DOUBLE_DIFF_THRESHOLD
Definition: qgscolorrampshader.cpp:23
QgsColorRampShader::setColorRampItemList
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom colormap.
Definition: qgscolorrampshader.cpp:99
qgscolorramplegendnodesettings.h
QgsRasterShaderFunction::minimumValue
double minimumValue() const
Returns the maximum value for the raster shader.
Definition: qgsrastershaderfunction.h:112
QgsSymbolLayerUtils::loadColorRamp
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
Definition: qgssymbollayerutils.cpp:3330
QgsGradientStopsList
QList< QgsGradientStop > QgsGradientStopsList
List of gradient stops.
Definition: qgscolorrampimpl.h:122
QgsColorRampShader::colorRampItemList
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Returns the custom colormap.
Definition: qgscolorrampshader.h:132
QgsColorRampShader::colorRampType
Type colorRampType() const
Returns the color ramp type.
Definition: qgscolorrampshader.h:135
QgsColorRampShader::operator=
QgsColorRampShader & operator=(const QgsColorRampShader &other)
Assignment operator.
Definition: qgscolorrampshader.cpp:65
QgsColorRampShader::ClassificationMode
ClassificationMode
Classification modes used to create the color ramp shader.
Definition: qgscolorrampshader.h:56
QgsRasterInterface
Base class for processing filters like renderers, reprojector, resampler etc.
Definition: qgsrasterinterface.h:135
QgsColorRampShader::shade
bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue) const override
Generates and new RGB value based on one input value.
Definition: qgscolorrampshader.cpp:381
QgsColorRampShader::readXml
void readXml(const QDomElement &elem, const QgsReadWriteContext &context=QgsReadWriteContext())
Reads configuration from the given DOM element.
Definition: qgscolorrampshader.cpp:599
QgsColorRampShader::clip
bool clip() const
Returns whether the shader will clip values which are out of range.
Definition: qgscolorrampshader.h:232
QgsRasterShaderFunction::mLabelPrecision
int mLabelPrecision
Label precision.
Definition: qgsrastershaderfunction.h:149
QgsColorRamp::count
virtual int count() const =0
Returns number of defined colors, or -1 if undefined.
QgsColorRamp::color
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
QgsRasterShaderFunction
The raster shade function applies a shader to a pixel at render time - typically used to render grays...
Definition: qgsrastershaderfunction.h:34
QgsColorRampShader::mSourceColorRamp
std::unique_ptr< QgsColorRamp > mSourceColorRamp
Source color ramp.
Definition: qgscolorrampshader.h:255
QgsColorRampShader::classificationMode
ClassificationMode classificationMode() const
Returns the classification mode.
Definition: qgscolorrampshader.h:219
QgsColorRampShader::ColorRampItem::label
QString label
Definition: qgscolorrampshader.h:116
qgslogger.h
QgsColorRampShader::Interpolated
@ Interpolated
Interpolates the color between two class breaks linearly.
Definition: qgscolorrampshader.h:50
QgsGradientStop
Represents a color stop within a QgsGradientColorRamp color ramp.
Definition: qgscolorrampimpl.h:38
QgsGradientColorRamp::isDiscrete
bool isDiscrete() const
Returns true if the gradient is using discrete interpolation, rather than smoothly interpolating betw...
Definition: qgscolorrampimpl.h:207
QgsColorRampShader::ColorRampItem::value
double value
Definition: qgscolorrampshader.h:117
QgsColorRampLegendNodeSettings
Settings for a color ramp legend node.
Definition: qgscolorramplegendnodesettings.h:37
QgsColorRamp::value
virtual double value(int index) const =0
Returns relative value between [0,1] of color at specified index.
QgsRasterShaderFunction::setMinimumValue
virtual void setMinimumValue(double value)
Sets the minimum value for the raster shader.
Definition: qgsrastershaderfunction.cpp:38
QgsColorRampShader::setLegendSettings
void setLegendSettings(QgsColorRampLegendNodeSettings *settings)
Sets the color ramp shader legend settings.
Definition: qgscolorrampshader.cpp:646
QgsColorRampShader::legendSettings
const QgsColorRampLegendNodeSettings * legendSettings() const
Returns the color ramp shader legend settings.
Definition: qgscolorrampshader.cpp:641