31#include <QDomDocument>
38 , mContrastEnhancement( nullptr )
49 if ( mContrastEnhancement )
69 const int grayBand = elem.attribute( QStringLiteral(
"grayBand" ), QStringLiteral(
"-1" ) ).toInt();
73 if ( elem.attribute( QStringLiteral(
"gradient" ) ) == QLatin1String(
"WhiteToBlack" ) )
78 const QDomElement contrastEnhancementElem = elem.firstChildElement( QStringLiteral(
"contrastEnhancement" ) );
79 if ( !contrastEnhancementElem.isNull() )
83 ce->
readXml( contrastEnhancementElem );
87 auto legendSettings = std::make_unique< QgsColorRampLegendNodeSettings >();
96 mContrastEnhancement.reset( ce );
102 QgsDebugMsgLevel( QStringLiteral(
"width = %1 height = %2" ).arg( width ).arg( height ), 4 );
104 auto outputBlock = std::make_unique<QgsRasterBlock>();
107 return outputBlock.release();
110 const std::shared_ptr< QgsRasterBlock > inputBlock(
mInput->block( mGrayBand,
extent, width, height, feedback ) );
111 if ( !inputBlock || inputBlock->isEmpty() )
114 return outputBlock.release();
117 std::shared_ptr< QgsRasterBlock > alphaBlock;
122 if ( !alphaBlock || alphaBlock->isEmpty() )
125 return outputBlock.release();
130 alphaBlock = inputBlock;
135 return outputBlock.release();
139 bool isNoData =
false;
142 double grayVal = inputBlock->valueAndNoData( i, isNoData );
146 outputBlock->setColor( i, myDefaultColor );
157 const double alpha = alphaBlock->value( i );
160 outputBlock->setColor( i, myDefaultColor );
165 currentAlpha *= alpha / 255.0;
169 if ( mContrastEnhancement )
171 if ( !mContrastEnhancement->isValueInDisplayableRange( grayVal ) )
173 outputBlock->setColor( i, myDefaultColor );
176 grayVal = mContrastEnhancement->enhanceContrast( grayVal );
181 grayVal = 255 - grayVal;
186 outputBlock->setColor( i, qRgba( grayVal, grayVal, grayVal, 255 ) );
190 outputBlock->setColor( i, qRgba( currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * 255 ) );
194 return outputBlock.release();
214 else if ( band > 0 && band <= mInput->
bandCount() )
224 if ( parentElem.isNull() )
229 QDomElement rasterRendererElem = doc.createElement( QStringLiteral(
"rasterrenderer" ) );
232 rasterRendererElem.setAttribute( QStringLiteral(
"grayBand" ), mGrayBand );
237 gradient = QStringLiteral(
"BlackToWhite" );
241 gradient = QStringLiteral(
"WhiteToBlack" );
243 rasterRendererElem.setAttribute( QStringLiteral(
"gradient" ),
gradient );
245 if ( mContrastEnhancement )
247 QDomElement contrastElem = doc.createElement( QStringLiteral(
"contrastEnhancement" ) );
248 mContrastEnhancement->writeXml( doc, contrastElem );
249 rasterRendererElem.appendChild( contrastElem );
252 if ( mLegendSettings )
255 parentElem.appendChild( rasterRendererElem );
260 QList<QPair<QString, QColor> > symbolItems;
263 const QColor minColor = ( mGradient ==
BlackToWhite ) ? Qt::black : Qt::white;
264 const QColor maxColor = ( mGradient ==
BlackToWhite ) ? Qt::white : Qt::black;
265 symbolItems.push_back( qMakePair( QString::number( mContrastEnhancement->minimumValue() ), minColor ) );
266 symbolItems.push_back( qMakePair( QString::number( mContrastEnhancement->maximumValue() ), maxColor ) );
273 QList<QgsLayerTreeModelLegendNode *> res;
277 if ( !name.isEmpty() )
282 const QColor minColor = ( mGradient ==
BlackToWhite ) ? Qt::black : Qt::white;
283 const QColor maxColor = ( mGradient ==
BlackToWhite ) ? Qt::white : Qt::black;
286 mContrastEnhancement->minimumValue(),
287 mContrastEnhancement->maximumValue() );
295 if ( mGrayBand != -1 )
297 bandList << mGrayBand;
306 toSld( doc, element, context );
315 QDomNodeList elements = element.elementsByTagName( QStringLiteral(
"sld:RasterSymbolizer" ) );
316 if ( elements.size() == 0 )
320 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
325 QDomElement channelSelectionElem = doc.createElement( QStringLiteral(
"sld:ChannelSelection" ) );
326 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Opacity" ) );
327 if ( elements.size() != 0 )
329 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
333 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Geometry" ) );
334 if ( elements.size() != 0 )
336 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
340 rasterSymbolizerElem.insertBefore( channelSelectionElem, rasterSymbolizerElem.firstChild() );
345 QDomElement channelElem = doc.createElement( QStringLiteral(
"sld:GrayChannel" ) );
346 channelSelectionElem.appendChild( channelElem );
349 QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral(
"sld:SourceChannelName" ) );
350 sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( mGrayBand ) ) );
351 channelElem.appendChild( sourceChannelNameElem );
356 QDomElement contrastEnhancementElem = doc.createElement( QStringLiteral(
"sld:ContrastEnhancement" ) );
357 lContrastEnhancement->toSld( doc, contrastEnhancementElem );
363 switch ( lContrastEnhancement->contrastEnhancementAlgorithm() )
375 const QDomNodeList vendorOptions = contrastEnhancementElem.elementsByTagName( QStringLiteral(
"sld:VendorOption" ) );
376 for (
int i = 0; i < vendorOptions.size(); ++i )
378 QDomElement vendorOption = vendorOptions.at( i ).toElement();
379 if ( vendorOption.attribute( QStringLiteral(
"name" ) ) != QLatin1String(
"minValue" ) )
383 vendorOption.removeChild( vendorOption.firstChild() );
384 vendorOption.appendChild( doc.createTextNode( QString::number( myRasterBandStats.
minimumValue ) ) );
397 channelElem.appendChild( contrastEnhancementElem );
405 QDomElement colorMapElem = doc.createElement( QStringLiteral(
"sld:ColorMap" ) );
406 rasterSymbolizerElem.appendChild( colorMapElem );
415 QList< QPair< QString, QColor > > colorMapping( classes );
421 const QString lowValue = classes[0].first;
422 QColor lowColor = classes[0].second;
423 lowColor.setAlpha( 0 );
424 const QString highValue = classes[1].first;
425 QColor highColor = classes[1].second;
426 highColor.setAlpha( 0 );
428 colorMapping.prepend( QPair< QString, QColor >( lowValue, lowColor ) );
429 colorMapping.append( QPair< QString, QColor >( highValue, highColor ) );
434 colorMapping[0].first = QStringLiteral(
"0" );
435 colorMapping[1].first = QStringLiteral(
"255" );
445 for (
auto it = colorMapping.constBegin(); it != colorMapping.constEnd() ; ++it )
448 QDomElement lowColorMapEntryElem = doc.createElement( QStringLiteral(
"sld:ColorMapEntry" ) );
449 colorMapElem.appendChild( lowColorMapEntryElem );
450 lowColorMapEntryElem.setAttribute( QStringLiteral(
"color" ), it->second.name() );
451 lowColorMapEntryElem.setAttribute( QStringLiteral(
"quantity" ), it->first );
452 if ( it->second.alphaF() == 0.0 )
454 lowColorMapEntryElem.setAttribute( QStringLiteral(
"opacity" ), QString::number( it->second.alpha() ) );
462 return mLegendSettings.get();
467 if ( settings == mLegendSettings.get() )
469 mLegendSettings.reset( settings );
479 bool refreshed =
false;
481 min.size() >= 1 && max.size() >= 1 )
484 mContrastEnhancement->setMinimumValue( min[0] );
485 mContrastEnhancement->setMaximumValue( max[0] );
QFlags< RasterRendererFlag > RasterRendererFlags
Flags which control behavior of raster renderers.
@ InternalLayerOpacityHandling
The renderer internally handles the raster layer's opacity, so the default layer level opacity handli...
DataType
Raster data types.
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Settings for a color ramp legend node.
A legend node which renders a color ramp.
Handles contrast enhancement and clipping.
@ StretchToMinimumMaximum
Linear histogram.
@ StretchAndClipToMinimumMaximum
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
void readXml(const QDomElement &elem)
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Layer tree node points to a map layer.
The RasterBandStats struct is a container for statistics about a single raster band.
double minimumValue
The minimum cell value in the raster band.
Feedback object tailored for raster block reading.
QgsRasterInterface(QgsRasterInterface *input=nullptr)
QString displayBandName(int bandNumber) const
Generates a friendly, descriptive name for the specified bandNumber.
QgsRasterInterface * mInput
virtual QgsRectangle extent() const
Gets the extent of the interface.
virtual QgsRasterInterface * input() const
Current input.
QgsRasterRenderer(QgsRasterInterface *input=nullptr, const QString &type=QString())
Constructor for QgsRasterRenderer.
double mOpacity
Global alpha value (0-1).
int mAlphaBand
Read alpha value from band.
QgsRectangle mLastRectangleUsedByRefreshContrastEnhancementIfNeeded
To save computations and possible infinite cycle of notifications.
QRgb renderColorForNodataPixel() const
Returns the color for the renderer to use to represent nodata pixels.
std::unique_ptr< QgsRasterTransparency > mRasterTransparency
Raster transparency per color or value. Overwrites global alpha value.
void _writeXml(QDomDocument &doc, QDomElement &rasterRendererElem) const
Write upper class info into rasterrenderer element (called by writeXml method of subclasses).
int bandCount() const override
Gets number of bands.
void copyCommonProperties(const QgsRasterRenderer *other, bool copyMinMaxOrigin=true)
Copies common properties like opacity / transparency data from other renderer.
bool needsRefresh(const QgsRectangle &extent) const
Checks if the renderer needs to be refreshed according to extent.
virtual Q_DECL_DEPRECATED void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const
Used from subclasses to create SLD Rule elements following SLD v1.0 specs.
void readXml(const QDomElement &rendererElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
A container for the context for various read/write operations on objects.
A rectangle specified with double values.
Implementation of legend node interface for displaying arbitrary labels with icons.
void setLegendSettings(QgsColorRampLegendNodeSettings *settings)
Sets the color ramp shader legend settings.
QList< int > usesBands() const override
Returns a list of band numbers used by the renderer.
const QgsContrastEnhancement * contrastEnhancement() const
Gradient gradient() const
void setContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
Qgis::RasterRendererFlags flags() const override
Returns flags which dictate renderer behavior.
static QgsRasterRenderer * create(const QDomElement &elem, QgsRasterInterface *input)
Q_DECL_DEPRECATED void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const override
Used from subclasses to create SLD Rule elements following SLD v1.0 specs.
bool setInputBand(int band) override
Attempts to set the input band for the renderer.
Q_DECL_DEPRECATED void setGrayBand(int band)
QgsSingleBandGrayRenderer(QgsRasterInterface *input, int grayBand)
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
const QgsColorRampLegendNodeSettings * legendSettings() const
Returns the color ramp shader legend settings.
QList< QPair< QString, QColor > > legendSymbologyItems() const override
Returns symbology items if provided by renderer.
QList< QgsLayerTreeModelLegendNode * > createLegendNodes(QgsLayerTreeLayer *nodeLayer) override
Creates a set of legend nodes representing the renderer.
Q_DECL_DEPRECATED int grayBand() const
void setGradient(Gradient gradient)
int inputBand() const override
Returns the input band for the renderer, or -1 if no input band is available.
bool refresh(const QgsRectangle &extent, const QList< double > &min, const QList< double > &max, bool forceRefresh=false) override
Refreshes the renderer according to the min and max values associated with the extent.
QgsSingleBandGrayRenderer * clone() const override
Clone itself, create deep copy.
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void setExtraProperties(const QVariantMap &properties)
Sets the open ended set of properties that can drive/inform the SLD encoding.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)