23#define DOUBLE_DIFF_THRESHOLD 0.0  
   37  , mColorRampType( type )
 
   38  , mClassificationMode( classificationMode )
 
 
   50  , mColorRampType( other.mColorRampType )
 
   51  , mClassificationMode( other.mClassificationMode )
 
   53  , mLUTOffset( other.mLUTOffset )
 
   54  , mLUTFactor( other.mLUTFactor )
 
   55  , mLUTInitialized( other.mLUTInitialized )
 
   56  , mClip( other.mClip )
 
   61  mColorRampItemList = other.mColorRampItemList;
 
 
   66  QgsRasterShaderFunction::operator=( other );
 
   72  mColorRampType = other.mColorRampType;
 
   73  mClassificationMode = other.mClassificationMode;
 
   75  mLUTOffset = other.mLUTOffset;
 
   76  mLUTFactor = other.mLUTFactor;
 
   77  mLUTInitialized = other.mLUTInitialized;
 
   79  mColorRampItemList = other.mColorRampItemList;
 
 
   86  switch ( mColorRampType )
 
   89      return QStringLiteral( 
"INTERPOLATED" );
 
   91      return QStringLiteral( 
"DISCRETE" );
 
   93      return QStringLiteral( 
"EXACT" );
 
   95  return QStringLiteral( 
"Unknown" );
 
 
  100  mColorRampItemList = list.toVector();
 
  102  mLUTInitialized = 
false;
 
 
  113  return mColorRampItemList.isEmpty();
 
 
  118  if ( type == QLatin1String( 
"INTERPOLATED" ) )
 
  122  else if ( type == QLatin1String( 
"DISCRETE" ) )
 
 
  139  auto ramp = std::make_unique< QgsGradientColorRamp >();
 
  140  const int count = mColorRampItemList.size();
 
  143    const QColor none( 0, 0, 0, 0 );
 
  144    ramp->setColor1( none );
 
  145    ramp->setColor2( none );
 
  147  else if ( count == 1 )
 
  149    ramp->setColor1( mColorRampItemList[0].color );
 
  150    ramp->setColor2( mColorRampItemList[0].color );
 
  158    for ( 
int i = 0; i < count; i++ )
 
  160      const double offset = ( mColorRampItemList[i].value - min ) / ( max - min );
 
  163        ramp->setColor1( mColorRampItemList[i].color );
 
  167      else if ( i == count - 1 )
 
  169        ramp->setColor2( mColorRampItemList[i].color );
 
  175    ramp->setStops( stops );
 
  178  return ramp.release();
 
 
  193  QList<double> entryValues;
 
  194  QVector<QColor> entryColors;
 
  203      entryValues.push_back( min );
 
  205        entryValues.push_back( std::numeric_limits<double>::infinity() );
 
  206      for ( 
int i = 0; i < entryValues.size(); ++i )
 
  215      entryValues.reserve( numberOfEntries );
 
  218        double intervalDiff = max - min;
 
  222        if ( colorGradientRamp && colorGradientRamp->
isDiscrete() )
 
  230          intervalDiff *= ( numberOfEntries - 1 ) / 
static_cast<double>( numberOfEntries );
 
  234        for ( 
int i = 1; i < numberOfEntries; ++i )
 
  237          entryValues.push_back( min + value * intervalDiff );
 
  239        entryValues.push_back( std::numeric_limits<double>::infinity() );
 
  243        for ( 
int i = 0; i < numberOfEntries; ++i )
 
  246          entryValues.push_back( min + value * ( max - min ) );
 
  250      for ( 
int i = 0; i < numberOfEntries; ++i )
 
  265      if ( band < 0 || !input )
 
  268      double cut1 = std::numeric_limits<double>::quiet_NaN();
 
  269      double cut2 = std::numeric_limits<double>::quiet_NaN();
 
  271      const int sampleSize = 250000 * 10;
 
  274      input->
cumulativeCut( band, 0.0, 1.0, min, max, extent, sampleSize );
 
  276      entryValues.reserve( classes );
 
  279        const double intervalDiff = 1.0 / ( classes );
 
  280        for ( 
int i = 1; i < classes; ++i )
 
  282          input->
cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
 
  283          entryValues.push_back( cut2 );
 
  285        entryValues.push_back( std::numeric_limits<double>::infinity() );
 
  289        const double intervalDiff = 1.0 / ( classes - 1 );
 
  290        for ( 
int i = 0; i < classes; ++i )
 
  292          input->
cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
 
  293          entryValues.push_back( cut2 );
 
  299      entryValues.reserve( classes );
 
  305        const double intervalDiff = ( max - min ) / ( classes );
 
  307        for ( 
int i = 1; i < classes; ++i )
 
  309          entryValues.push_back( min + i * intervalDiff );
 
  311        entryValues.push_back( std::numeric_limits<double>::infinity() );
 
  316        const double intervalDiff = ( max - min ) / ( classes - 1 );
 
  318        for ( 
int i = 0; i < classes; ++i )
 
  320          entryValues.push_back( min + i * intervalDiff );
 
  331        colorDiff = ( int )( 255 / classes );
 
  334      entryColors.reserve( classes );
 
  335      for ( 
int i = 0; i < classes; ++i )
 
  339        currentColor.setRgb( colorDiff * idx, 0, 255 - colorDiff * idx );
 
  340        entryColors.push_back( currentColor );
 
  345      entryColors.reserve( classes );
 
  346      for ( 
int i = 0; i < classes; ++i )
 
  354  QList<double>::const_iterator value_it = entryValues.constBegin();
 
  355  QVector<QColor>::const_iterator color_it = entryColors.constBegin();
 
  358  const double maxabs = std::log10( std::max( std::fabs( max ), std::fabs( min ) ) );
 
  359  const int nDecimals = std::round( std::max( 3.0 + maxabs - std::log10( max - min ), maxabs <= 15.0 ? maxabs + 0.49 : 0.0 ) );
 
  361  QList<QgsColorRampShader::ColorRampItem> colorRampItems;
 
  362  for ( ; value_it != entryValues.constEnd(); ++value_it, ++color_it )
 
  365    newColorRampItem.
value = *value_it;
 
  366    newColorRampItem.
color = *color_it;
 
  367    newColorRampItem.
label = QString::number( *value_it, 
'g', nDecimals );
 
  368    colorRampItems.append( newColorRampItem );
 
  371  std::sort( colorRampItems.begin(), colorRampItems.end() );
 
 
  380bool QgsColorRampShader::shade( 
double value, 
int *returnRedValue, 
int *returnGreenValue, 
int *returnBlueValue, 
int *returnAlphaValue )
 const 
  382  const int colorRampItemListCount = mColorRampItemList.count();
 
  383  if ( colorRampItemListCount == 0 )
 
  387  if ( std::isnan( value ) || std::isinf( value ) )
 
  392  if ( !mLUTInitialized )
 
  399    if ( colorRampItemListCount >= 3 )
 
  401      const double rangeValue = colorRampItems[colorRampItemListCount - 2].
value - 
minimumValue;
 
  402      if ( rangeValue > 0 )
 
  404        const int lutSize = 256; 
 
  405        mLUTFactor = ( lutSize - 0.0000001 ) / rangeValue; 
 
  408        mLUT.reserve( lutSize );
 
  409        for ( 
int i = 0; i < lutSize; i++ )
 
  411          val = ( i / mLUTFactor ) + mLUTOffset;
 
  412          while ( idx < colorRampItemListCount
 
  417          mLUT.emplace_back( idx );
 
  421    mLUTInitialized = 
true;
 
  426  bool overflow = 
false;
 
  429  const int lutIndex = ( value - mLUTOffset ) * mLUTFactor;
 
  430  if ( value <= mLUTOffset )
 
  434  else if ( 
static_cast< std::size_t
>( lutIndex ) >= mLUT.size() )
 
  436    idx = colorRampItemListCount - 1;
 
  442  else if ( lutIndex < 0 )
 
  449    idx = mLUT[ lutIndex ];
 
  457    if ( idx >= colorRampItemListCount )
 
  459      idx = colorRampItemListCount - 1;
 
  466  switch ( mColorRampType )
 
  473        if ( mClip && ( overflow
 
  478        *returnRedValue   = currentColorRampItem.
color.red();
 
  479        *returnGreenValue = currentColorRampItem.
color.green();
 
  480        *returnBlueValue  = currentColorRampItem.
color.blue();
 
  481        *returnAlphaValue = currentColorRampItem.
color.alpha();
 
  487      const float currentRampRange = currentColorRampItem.
value - previousColorRampItem.
value;
 
  488      const float offsetInRange = value - previousColorRampItem.
value;
 
  489      const float scale = offsetInRange / currentRampRange;
 
  491      const int c1Red = previousColorRampItem.
color.red();
 
  492      const int c1Green = previousColorRampItem.
color.green();
 
  493      const int c1Blue = previousColorRampItem.
color.blue();
 
  494      const int c1Alpha = previousColorRampItem.
color.alpha();
 
  496      const int c2Red = currentColorRampItem.
color.red();
 
  497      const int c2Green = currentColorRampItem.
color.green();
 
  498      const int c2Blue = currentColorRampItem.
color.blue();
 
  499      const int c2Alpha = currentColorRampItem.
color.alpha();
 
  501      *returnRedValue   = c1Red   + 
static_cast< int >( ( c2Red - c1Red )   * scale );
 
  502      *returnGreenValue = c1Green + 
static_cast< int >( ( c2Green - c1Green ) * scale );
 
  503      *returnBlueValue  = c1Blue  + 
static_cast< int >( ( c2Blue - c1Blue )  * scale );
 
  504      *returnAlphaValue = c1Alpha + 
static_cast< int >( ( c2Alpha - c1Alpha ) * scale );
 
  516      *returnRedValue   = currentColorRampItem.
color.red();
 
  517      *returnGreenValue = currentColorRampItem.
color.green();
 
  518      *returnBlueValue  = currentColorRampItem.
color.blue();
 
  519      *returnAlphaValue = currentColorRampItem.
color.alpha();
 
  527        *returnRedValue   = currentColorRampItem.
color.red();
 
  528        *returnGreenValue = currentColorRampItem.
color.green();
 
  529        *returnBlueValue  = currentColorRampItem.
color.blue();
 
  530        *returnAlphaValue = currentColorRampItem.
color.alpha();
 
 
  543                                double blueValue, 
double alphaValue,
 
  544                                int *returnRedValue, 
int *returnGreenValue,
 
  545                                int *returnBlueValue, 
int *returnAlphaValue )
 const 
  548  Q_UNUSED( greenValue )
 
  549  Q_UNUSED( blueValue )
 
  550  Q_UNUSED( alphaValue )
 
  553  *returnGreenValue = 0;
 
  554  *returnBlueValue = 0;
 
  555  *returnAlphaValue = 0;
 
 
  562  QVector<QgsColorRampShader::ColorRampItem>::const_iterator colorRampIt = mColorRampItemList.constBegin();
 
  563  for ( ; colorRampIt != mColorRampItemList.constEnd(); ++colorRampIt )
 
  565    symbolItems.push_back( qMakePair( colorRampIt->label, colorRampIt->color ) );
 
 
  571  QDomElement colorRampShaderElem = doc.createElement( QStringLiteral( 
"colorrampshader" ) );
 
  573  colorRampShaderElem.setAttribute( QStringLiteral( 
"classificationMode" ), 
static_cast< int >( 
classificationMode() ) );
 
  574  colorRampShaderElem.setAttribute( QStringLiteral( 
"clip" ), 
clip() );
 
  575  colorRampShaderElem.setAttribute( QStringLiteral( 
"minimumValue" ), 
mMinimumValue );
 
  576  colorRampShaderElem.setAttribute( QStringLiteral( 
"maximumValue" ), 
mMaximumValue );
 
  577  colorRampShaderElem.setAttribute( QStringLiteral( 
"labelPrecision" ), 
mLabelPrecision );
 
  583    colorRampShaderElem.appendChild( colorRampElem );
 
  588  QList<QgsColorRampShader::ColorRampItem>::const_iterator itemIt = itemList.constBegin();
 
  589  for ( ; itemIt != itemList.constEnd(); ++itemIt )
 
  591    QDomElement itemElem = doc.createElement( QStringLiteral( 
"item" ) );
 
  592    itemElem.setAttribute( QStringLiteral( 
"label" ), itemIt->label );
 
  594    itemElem.setAttribute( QStringLiteral( 
"color" ), itemIt->color.name() );
 
  595    itemElem.setAttribute( QStringLiteral( 
"alpha" ), itemIt->color.alpha() );
 
  596    colorRampShaderElem.appendChild( itemElem );
 
  599  if ( mLegendSettings )
 
  600    mLegendSettings->writeXml( doc, colorRampShaderElem, context );
 
  602  return colorRampShaderElem;
 
 
  608  QDomElement sourceColorRampElem = colorRampShaderElem.firstChildElement( QStringLiteral( 
"colorramp" ) );
 
  609  if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( 
"name" ) ) == QLatin1String( 
"[source]" ) )
 
  614  setColorRampType( colorRampShaderElem.attribute( QStringLiteral( 
"colorRampType" ), QStringLiteral( 
"INTERPOLATED" ) ) );
 
  616  setClip( colorRampShaderElem.attribute( QStringLiteral( 
"clip" ), QStringLiteral( 
"0" ) ) == QLatin1String( 
"1" ) );
 
  617  setMinimumValue( colorRampShaderElem.attribute( QStringLiteral( 
"minimumValue" ) ).toDouble() );
 
  618  setMaximumValue( colorRampShaderElem.attribute( QStringLiteral( 
"maximumValue" ) ).toDouble() );
 
  619  setLabelPrecision( colorRampShaderElem.attribute( QStringLiteral( 
"labelPrecision" ), QStringLiteral( 
"6" ) ).toDouble() );
 
  621  QList<QgsColorRampShader::ColorRampItem> itemList;
 
  622  QDomElement itemElem;
 
  627  const QDomNodeList itemNodeList = colorRampShaderElem.elementsByTagName( QStringLiteral( 
"item" ) );
 
  628  itemList.reserve( itemNodeList.size() );
 
  629  for ( 
int i = 0; i < itemNodeList.size(); ++i )
 
  631    itemElem = itemNodeList.at( i ).toElement();
 
  632    itemValue = itemElem.attribute( QStringLiteral( 
"value" ) ).toDouble();
 
  633    itemLabel = itemElem.attribute( QStringLiteral( 
"label" ) );
 
  634    itemColor.setNamedColor( itemElem.attribute( QStringLiteral( 
"color" ) ) );
 
  635    itemColor.setAlpha( itemElem.attribute( QStringLiteral( 
"alpha" ), QStringLiteral( 
"255" ) ).toInt() );
 
  641  if ( !mLegendSettings )
 
  642    mLegendSettings = std::make_unique< QgsColorRampLegendNodeSettings >();
 
  644  mLegendSettings->readXml( colorRampShaderElem, context );
 
 
  649  return mLegendSettings.get();
 
 
  654  if ( settings == mLegendSettings.get() )
 
  656  mLegendSettings.reset( settings );
 
 
ShaderInterpolationMethod
Color ramp shader interpolation methods.
 
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
 
@ Linear
Interpolates the color between two class breaks linearly.
 
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
 
ShaderClassificationMethod
Color ramp shader classification methods.
 
@ Continuous
Uses breaks from color palette.
 
@ Quantile
Uses quantile (i.e. equal pixel) count.
 
Settings for a color ramp legend node.
 
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
 
~QgsColorRampShader() override
 
void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const override
Returns legend symbology items if provided by renderer.
 
Qgis::ShaderClassificationMethod classificationMode() const
Returns the classification mode.
 
Qgis::ShaderInterpolationMethod colorRampType() const
Returns the color ramp interpolation method.
 
const QgsColorRampLegendNodeSettings * legendSettings() const
Returns the color ramp shader legend settings.
 
bool isEmpty() const
Whether the color ramp contains any items.
 
void setSourceColorRamp(QgsColorRamp *colorramp)
Set the source color ramp.
 
void setClassificationMode(Qgis::ShaderClassificationMethod classificationMode)
Sets the classification mode.
 
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Returns the custom color map.
 
QgsColorRampShader & operator=(const QgsColorRampShader &other)
 
void setClip(bool clip)
Sets whether the shader should not render values out of range.
 
bool clip() const
Returns whether the shader will clip values which are out of range.
 
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context=QgsReadWriteContext()) const
Writes configuration to a new DOM element.
 
bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue) const override
Generates an new RGBA value based on one input value.
 
QgsColorRamp * sourceColorRamp() const
Returns the source color ramp.
 
QgsColorRamp * createColorRamp() const
Creates a gradient color ramp from shader settings.
 
void classifyColorRamp(int classes=0, int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
 
void setColorRampType(Qgis::ShaderInterpolationMethod colorRampType)
Sets the color ramp interpolation method.
 
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom color map.
 
QString colorRampTypeAsQString() const
Returns the color ramp type as a string.
 
void readXml(const QDomElement &elem, const QgsReadWriteContext &context=QgsReadWriteContext())
Reads configuration from the given DOM element.
 
QgsColorRampShader(double minimumValue=0.0, double maximumValue=255.0, QgsColorRamp *colorRamp=nullptr, Qgis::ShaderInterpolationMethod type=Qgis::ShaderInterpolationMethod::Linear, Qgis::ShaderClassificationMethod classificationMode=Qgis::ShaderClassificationMethod::Continuous)
Creates a new color ramp shader.
 
std::unique_ptr< QgsColorRamp > mSourceColorRamp
Source color ramp.
 
void setLegendSettings(QgsColorRampLegendNodeSettings *settings)
Sets the color ramp shader legend settings.
 
Abstract base class for color ramps.
 
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
 
virtual int count() const =0
Returns number of defined colors, or -1 if undefined.
 
virtual double value(int index) const =0
Returns relative value between [0,1] of color at specified index.
 
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
 
bool isDiscrete() const
Returns true if the gradient is using discrete interpolation, rather than smoothly interpolating betw...
 
Represents a color stop within a QgsGradientColorRamp color ramp.
 
static QString printValue(double value, bool localized=false)
Print double value with all necessary significant digits.
 
Base class for processing filters like renderers, reprojector, resampler etc.
 
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.
 
The raster shade function applies a shader to a pixel at render time - typically used to render grays...
 
double mMinimumValue
User defineable minimum value for the shading function.
 
double maximumValue() const
Returns the minimum value for the raster shader.
 
double mMaximumValue
User defineable maximum value for the shading function.
 
void setLabelPrecision(int labelPrecision)
Sets label precision to labelPrecision.
 
virtual void setMaximumValue(double value)
Sets the maximum value for the raster shader.
 
virtual void setMinimumValue(double value)
Sets the minimum value for the raster shader.
 
int mLabelPrecision
Label precision.
 
double minimumValue() const
Returns the maximum value for the raster shader.
 
A container for the context for various read/write operations on objects.
 
A rectangle specified with double values.
 
static std::unique_ptr< QgsColorRamp > loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
 
static QDomElement saveColorRamp(const QString &name, const QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
 
QList< QgsGradientStop > QgsGradientStopsList
List of gradient stops.
 
#define DOUBLE_DIFF_THRESHOLD
 
#define QgsDebugMsgLevel(str, level)