23 #define DOUBLE_DIFF_THRESHOLD 0.0  
   38   , mColorRampType( type )
 
   39   , mClassificationMode( classificationMode )
 
   51   , mColorRampType( other.mColorRampType )
 
   52   , mClassificationMode( other.mClassificationMode )
 
   54   , mLUTOffset( other.mLUTOffset )
 
   55   , mLUTFactor( other.mLUTFactor )
 
   56   , mLUTInitialized( other.mLUTInitialized )
 
   57   , mClip( other.mClip )
 
   62   mColorRampItemList = other.mColorRampItemList;
 
   67   QgsRasterShaderFunction::operator=( other );
 
   73   mColorRampType = other.mColorRampType;
 
   74   mClassificationMode = other.mClassificationMode;
 
   76   mLUTOffset = other.mLUTOffset;
 
   77   mLUTFactor = other.mLUTFactor;
 
   78   mLUTInitialized = other.mLUTInitialized;
 
   80   mColorRampItemList = other.mColorRampItemList;
 
   87   switch ( mColorRampType )
 
   90       return QStringLiteral( 
"INTERPOLATED" );
 
   92       return QStringLiteral( 
"DISCRETE" );
 
   94       return QStringLiteral( 
"EXACT" );
 
   96   return QStringLiteral( 
"Unknown" );
 
  101   mColorRampItemList = list.toVector();
 
  103   mLUTInitialized = 
false;
 
  114   return mColorRampItemList.isEmpty();
 
  119   if ( type == QLatin1String( 
"INTERPOLATED" ) )
 
  123   else if ( type == QLatin1String( 
"DISCRETE" ) )
 
  129     mColorRampType = 
Exact;
 
  140   std::unique_ptr<QgsGradientColorRamp> ramp = std::make_unique< QgsGradientColorRamp >();
 
  141   int count = mColorRampItemList.size();
 
  144     const QColor none( 0, 0, 0, 0 );
 
  145     ramp->setColor1( none );
 
  146     ramp->setColor2( none );
 
  148   else if ( count == 1 )
 
  150     ramp->setColor1( mColorRampItemList[0].color );
 
  151     ramp->setColor2( mColorRampItemList[0].color );
 
  159     for ( 
int i = 0; i < count; i++ )
 
  161       double offset = ( mColorRampItemList[i].value - min ) / ( max - min );
 
  164         ramp->setColor1( mColorRampItemList[i].color );
 
  168       else if ( i == count - 1 )
 
  170         ramp->setColor2( mColorRampItemList[i].color );
 
  176     ramp->setStops( stops );
 
  179   return ramp.release();
 
  194   QList<double> entryValues;
 
  195   QVector<QColor> entryColors;
 
  204       entryValues.push_back( min );
 
  206         entryValues.push_back( std::numeric_limits<double>::infinity() );
 
  207       for ( 
int i = 0; i < entryValues.size(); ++i )
 
  216       entryValues.reserve( numberOfEntries );
 
  219         double intervalDiff = max - min;
 
  223         if ( colorGradientRamp && colorGradientRamp->
isDiscrete() )
 
  231           intervalDiff *= ( numberOfEntries - 1 ) / 
static_cast<double>( numberOfEntries );
 
  235         for ( 
int i = 1; i < numberOfEntries; ++i )
 
  238           entryValues.push_back( min + value * intervalDiff );
 
  240         entryValues.push_back( std::numeric_limits<double>::infinity() );
 
  244         for ( 
int i = 0; i < numberOfEntries; ++i )
 
  247           entryValues.push_back( min + value * ( max - min ) );
 
  251       for ( 
int i = 0; i < numberOfEntries; ++i )
 
  266       if ( band < 0 || !input )
 
  269       double cut1 = std::numeric_limits<double>::quiet_NaN();
 
  270       double cut2 = std::numeric_limits<double>::quiet_NaN();
 
  272       const int sampleSize = 250000 * 10;
 
  275       input->
cumulativeCut( band, 0.0, 1.0, min, max, extent, sampleSize );
 
  277       entryValues.reserve( classes );
 
  280         double intervalDiff = 1.0 / ( classes );
 
  281         for ( 
int i = 1; i < classes; ++i )
 
  283           input->
cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
 
  284           entryValues.push_back( cut2 );
 
  286         entryValues.push_back( std::numeric_limits<double>::infinity() );
 
  290         double intervalDiff = 1.0 / ( classes - 1 );
 
  291         for ( 
int i = 0; i < classes; ++i )
 
  293           input->
cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
 
  294           entryValues.push_back( cut2 );
 
  300       entryValues.reserve( classes );
 
  306         double intervalDiff = ( max - min ) / ( classes );
 
  308         for ( 
int i = 1; i < classes; ++i )
 
  310           entryValues.push_back( min + i * intervalDiff );
 
  312         entryValues.push_back( std::numeric_limits<double>::infinity() );
 
  317         double intervalDiff = ( max - min ) / ( classes - 1 );
 
  319         for ( 
int i = 0; i < classes; ++i )
 
  321           entryValues.push_back( min + i * intervalDiff );
 
  332         colorDiff = ( int )( 255 / classes );
 
  335       entryColors.reserve( classes );
 
  336       for ( 
int i = 0; i < classes; ++i )
 
  340         currentColor.setRgb( colorDiff * idx, 0, 255 - colorDiff * idx );
 
  341         entryColors.push_back( currentColor );
 
  346       entryColors.reserve( classes );
 
  347       for ( 
int i = 0; i < classes; ++i )
 
  355   QList<double>::const_iterator value_it = entryValues.constBegin();
 
  356   QVector<QColor>::const_iterator color_it = entryColors.constBegin();
 
  359   double maxabs = std::log10( std::max( std::fabs( max ), std::fabs( min ) ) );
 
  360   int nDecimals = std::round( std::max( 3.0 + maxabs - std::log10( max - min ), maxabs <= 15.0 ? maxabs + 0.49 : 0.0 ) );
 
  362   QList<QgsColorRampShader::ColorRampItem> colorRampItems;
 
  363   for ( ; value_it != entryValues.constEnd(); ++value_it, ++color_it )
 
  366     newColorRampItem.
value = *value_it;
 
  367     newColorRampItem.
color = *color_it;
 
  368     newColorRampItem.
label = QString::number( *value_it, 
'g', nDecimals );
 
  369     colorRampItems.append( newColorRampItem );
 
  372   std::sort( colorRampItems.begin(), colorRampItems.end() );
 
  381 bool QgsColorRampShader::shade( 
double value, 
int *returnRedValue, 
int *returnGreenValue, 
int *returnBlueValue, 
int *returnAlphaValue )
 const 
  383   if ( mColorRampItemList.isEmpty() )
 
  387   if ( std::isnan( value ) || std::isinf( value ) )
 
  390   int colorRampItemListCount = mColorRampItemList.count();
 
  393   if ( !mLUTInitialized )
 
  400     if ( colorRampItemListCount >= 3 )
 
  402       double rangeValue = colorRampItems[colorRampItemListCount - 2].
value - 
minimumValue;
 
  403       if ( rangeValue > 0 )
 
  406         mLUTFactor = ( lutSize - 0.0000001 ) / rangeValue; 
 
  409         mLUT.reserve( lutSize );
 
  410         for ( 
int i = 0; i < lutSize; i++ )
 
  412           val = ( i / mLUTFactor ) + mLUTOffset;
 
  413           while ( idx < colorRampItemListCount
 
  418           mLUT.emplace_back( idx );
 
  422     mLUTInitialized = 
true;
 
  427   bool overflow = 
false;
 
  430   int lutIndex = ( value - mLUTOffset ) * mLUTFactor;
 
  431   if ( value < mLUTOffset )
 
  435   else if ( 
static_cast< std::size_t
>( lutIndex ) >= mLUT.size() )
 
  437     idx = colorRampItemListCount - 1;
 
  443   else if ( lutIndex < 0 )
 
  450     idx = mLUT[ lutIndex ];
 
  458     if ( idx >= colorRampItemListCount )
 
  460       idx = colorRampItemListCount - 1;
 
  474         if ( mClip && ( overflow
 
  479         *returnRedValue   = currentColorRampItem.
color.red();
 
  480         *returnGreenValue = currentColorRampItem.
color.green();
 
  481         *returnBlueValue  = currentColorRampItem.
color.blue();
 
  482         *returnAlphaValue = currentColorRampItem.
color.alpha();
 
  488       float currentRampRange = currentColorRampItem.
value - previousColorRampItem.
value;
 
  489       float offsetInRange = value - previousColorRampItem.
value;
 
  490       float scale = offsetInRange / currentRampRange;
 
  492       const QRgb c1 = previousColorRampItem.
color.rgba();
 
  493       const QRgb c2 = currentColorRampItem.
color.rgba();
 
  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 );
 
  510       *returnRedValue   = currentColorRampItem.
color.red();
 
  511       *returnGreenValue = currentColorRampItem.
color.green();
 
  512       *returnBlueValue  = currentColorRampItem.
color.blue();
 
  513       *returnAlphaValue = currentColorRampItem.
color.alpha();
 
  521         *returnRedValue   = currentColorRampItem.
color.red();
 
  522         *returnGreenValue = currentColorRampItem.
color.green();
 
  523         *returnBlueValue  = currentColorRampItem.
color.blue();
 
  524         *returnAlphaValue = currentColorRampItem.
color.alpha();
 
  537                                 double blueValue, 
double alphaValue,
 
  538                                 int *returnRedValue, 
int *returnGreenValue,
 
  539                                 int *returnBlueValue, 
int *returnAlphaValue )
 const 
  542   Q_UNUSED( greenValue )
 
  543   Q_UNUSED( blueValue )
 
  544   Q_UNUSED( alphaValue )
 
  547   *returnGreenValue = 0;
 
  548   *returnBlueValue = 0;
 
  549   *returnAlphaValue = 0;
 
  556   QVector<QgsColorRampShader::ColorRampItem>::const_iterator colorRampIt = mColorRampItemList.constBegin();
 
  557   for ( ; colorRampIt != mColorRampItemList.constEnd(); ++colorRampIt )
 
  559     symbolItems.push_back( qMakePair( colorRampIt->label, colorRampIt->color ) );
 
  565   QDomElement colorRampShaderElem = doc.createElement( QStringLiteral( 
"colorrampshader" ) );
 
  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 );
 
  577     colorRampShaderElem.appendChild( colorRampElem );
 
  582   QList<QgsColorRampShader::ColorRampItem>::const_iterator itemIt = itemList.constBegin();
 
  583   for ( ; itemIt != itemList.constEnd(); ++itemIt )
 
  585     QDomElement itemElem = doc.createElement( QStringLiteral( 
"item" ) );
 
  586     itemElem.setAttribute( QStringLiteral( 
"label" ), itemIt->label );
 
  588     itemElem.setAttribute( QStringLiteral( 
"color" ), itemIt->color.name() );
 
  589     itemElem.setAttribute( QStringLiteral( 
"alpha" ), itemIt->color.alpha() );
 
  590     colorRampShaderElem.appendChild( itemElem );
 
  593   if ( mLegendSettings )
 
  594     mLegendSettings->writeXml( doc, colorRampShaderElem, context );
 
  596   return colorRampShaderElem;
 
  602   QDomElement sourceColorRampElem = colorRampShaderElem.firstChildElement( QStringLiteral( 
"colorramp" ) );
 
  603   if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( 
"name" ) ) == QLatin1String( 
"[source]" ) )
 
  608   setColorRampType( colorRampShaderElem.attribute( QStringLiteral( 
"colorRampType" ), QStringLiteral( 
"INTERPOLATED" ) ) );
 
  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() );
 
  615   QList<QgsColorRampShader::ColorRampItem> itemList;
 
  616   QDomElement itemElem;
 
  621   QDomNodeList itemNodeList = colorRampShaderElem.elementsByTagName( QStringLiteral( 
"item" ) );
 
  622   itemList.reserve( itemNodeList.size() );
 
  623   for ( 
int i = 0; i < itemNodeList.size(); ++i )
 
  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() );
 
  635   if ( !mLegendSettings )
 
  636     mLegendSettings = std::make_unique< QgsColorRampLegendNodeSettings >();
 
  638   mLegendSettings->readXml( colorRampShaderElem, context );
 
  643   return mLegendSettings.get();
 
  648   if ( settings == mLegendSettings.get() )
 
  650   mLegendSettings.reset( settings );
 
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
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Returns the custom colormap.
void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const override
Returns legend symbology items if provided by renderer.
ClassificationMode classificationMode() const
Returns the classification mode.
const QgsColorRampLegendNodeSettings * legendSettings() const
Returns the color ramp shader legend settings.
bool isEmpty() const
Whether the color ramp contains any items.
Type colorRampType() const
Returns the color ramp type.
void setSourceColorRamp(QgsColorRamp *colorramp)
Set the source color ramp.
QgsColorRampShader & operator=(const QgsColorRampShader &other)
Assignment operator.
ClassificationMode
Classification modes used to create the color ramp shader.
@ Quantile
Uses quantile (i.e. equal pixel) count.
@ Continuous
Uses breaks from color palette.
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 and new RGB 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.
Type
Supported methods for color interpolation.
@ Interpolated
Interpolates the color between two class breaks linearly.
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
void setClassificationMode(ClassificationMode classificationMode)
Sets classification mode.
void classifyColorRamp(int classes=0, int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom colormap.
void setColorRampType(QgsColorRampShader::Type colorRampType)
Sets the color ramp type.
QgsColorRampShader(double minimumValue=0.0, double maximumValue=255.0, QgsColorRamp *colorRamp=nullptr, Type type=Interpolated, ClassificationMode classificationMode=Continuous)
Creates a new color ramp shader.
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.
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)
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.
The class is used as a container of context for various read/write operations on other objects.
A rectangle specified with double values.
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static QDomElement saveColorRamp(const QString &name, 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)