24#include <QDomDocument>
35 , mGreenBand( greenBand )
36 , mBlueBand( blueBand )
37 , mRedContrastEnhancement( redEnhancement )
38 , mGreenContrastEnhancement( greenEnhancement )
39 , mBlueContrastEnhancement( blueEnhancement )
50 if ( mRedContrastEnhancement )
54 if ( mGreenContrastEnhancement )
58 if ( mBlueContrastEnhancement )
73 if ( ce == mRedContrastEnhancement.get() )
76 mRedContrastEnhancement.reset( ce );
81 return mGreenContrastEnhancement.get();
86 if ( ce == mGreenContrastEnhancement.get() )
89 mGreenContrastEnhancement.reset( ce );
94 return mBlueContrastEnhancement.get();
99 if ( ce == mBlueContrastEnhancement.get() )
102 mBlueContrastEnhancement.reset( ce );
113 const int redBand = elem.attribute( QStringLiteral(
"redBand" ), QStringLiteral(
"-1" ) ).toInt();
114 const int greenBand = elem.attribute( QStringLiteral(
"greenBand" ), QStringLiteral(
"-1" ) ).toInt();
115 const int blueBand = elem.attribute( QStringLiteral(
"blueBand" ), QStringLiteral(
"-1" ) ).toInt();
119 const QDomElement redContrastElem = elem.firstChildElement( QStringLiteral(
"redContrastEnhancement" ) );
120 if ( !redContrastElem.isNull() )
128 const QDomElement greenContrastElem = elem.firstChildElement( QStringLiteral(
"greenContrastEnhancement" ) );
129 if ( !greenContrastElem.isNull() )
137 const QDomElement blueContrastElem = elem.firstChildElement( QStringLiteral(
"blueContrastEnhancement" ) );
138 if ( !blueContrastElem.isNull() )
154 auto outputBlock = std::make_unique<QgsRasterBlock>();
157 return outputBlock.release();
162 && mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
170 if ( mGreenBand > 0 )
182 return outputBlock.release();
190 QMap<int, QgsRasterBlock *> bandBlocks;
192 QList<int>::const_iterator bandIt = bands.constBegin();
193 for ( ; bandIt != bands.constEnd(); ++bandIt )
195 bandBlocks.insert( *bandIt, defaultPointer );
203 bandIt = bands.constBegin();
204 for ( ; bandIt != bands.constEnd(); ++bandIt )
207 if ( !bandBlocks[*bandIt] )
212 for ( ; bandIt != bands.constBegin(); --bandIt )
214 delete bandBlocks[*bandIt];
216 return outputBlock.release();
222 redBlock = bandBlocks[mRedBand];
224 if ( mGreenBand > 0 )
226 greenBlock = bandBlocks[mGreenBand];
230 blueBlock = bandBlocks[mBlueBand];
239 for (
int i = 0; i < bandBlocks.size(); i++ )
241 delete bandBlocks.
value( i );
243 return outputBlock.release();
246 QRgb *outputBlockColorData = outputBlock->colorData();
250 const quint8 *redData =
nullptr, *greenData =
nullptr, *blueData =
nullptr;
275 hasEnhancement = mRedContrastEnhancement || mGreenContrastEnhancement || mBlueContrastEnhancement;
277 if ( hasEnhancement )
282 for (
qgssize i = 0; i < count; i++ )
292 outputBlock->setColor( i, myDefaultColor );
296 outputBlockColorData[i] = qRgb( redData[i], greenData[i], blueData[i] );
301 bool redIsNoData =
false;
302 bool greenIsNoData =
false;
303 bool blueIsNoData =
false;
313 if ( !redIsNoData && !greenIsNoData )
320 outputBlock->setColor( i, myDefaultColor );
324 outputBlockColorData[i] = qRgb( redVal, greenVal, blueVal );
330 bool isNoData =
false;
338 if ( !isNoData && mGreenBand > 0 )
342 if ( !isNoData && mBlueBand > 0 )
348 outputBlock->setColor( i, myDefaultColor );
353 if ( ( mRedContrastEnhancement && !mRedContrastEnhancement->isValueInDisplayableRange( redVal ) )
354 || ( mGreenContrastEnhancement && !mGreenContrastEnhancement->isValueInDisplayableRange( redVal ) )
355 || ( mBlueContrastEnhancement && !mBlueContrastEnhancement->isValueInDisplayableRange( redVal ) ) )
357 outputBlock->setColor( i, myDefaultColor );
362 if ( mRedContrastEnhancement )
364 redVal = mRedContrastEnhancement->enhanceContrast( redVal );
366 if ( mGreenContrastEnhancement )
368 greenVal = mGreenContrastEnhancement->enhanceContrast( greenVal );
370 if ( mBlueContrastEnhancement )
372 blueVal = mBlueContrastEnhancement->enhanceContrast( blueVal );
383 const double alpha = alphaBlock->
value( i );
386 outputBlock->setColor( i, myDefaultColor );
391 currentOpacity *= alpha / 255.0;
397 outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
401 outputBlock->setColor( i, qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 ) );
406 QMap<int, QgsRasterBlock *>::const_iterator bandDelIt = bandBlocks.constBegin();
407 for ( ; bandDelIt != bandBlocks.constEnd(); ++bandDelIt )
409 delete bandDelIt.value();
412 return outputBlock.release();
417 return mRedContrastEnhancement.get();
422 if ( parentElem.isNull() )
427 QDomElement rasterRendererElem = doc.createElement( QStringLiteral(
"rasterrenderer" ) );
429 rasterRendererElem.setAttribute( QStringLiteral(
"redBand" ), mRedBand );
430 rasterRendererElem.setAttribute( QStringLiteral(
"greenBand" ), mGreenBand );
431 rasterRendererElem.setAttribute( QStringLiteral(
"blueBand" ), mBlueBand );
434 if ( mRedContrastEnhancement )
436 QDomElement redContrastElem = doc.createElement( QStringLiteral(
"redContrastEnhancement" ) );
437 mRedContrastEnhancement->writeXml( doc, redContrastElem );
438 rasterRendererElem.appendChild( redContrastElem );
440 if ( mGreenContrastEnhancement )
442 QDomElement greenContrastElem = doc.createElement( QStringLiteral(
"greenContrastEnhancement" ) );
443 mGreenContrastEnhancement->writeXml( doc, greenContrastElem );
444 rasterRendererElem.appendChild( greenContrastElem );
446 if ( mBlueContrastEnhancement )
448 QDomElement blueContrastElem = doc.createElement( QStringLiteral(
"blueContrastEnhancement" ) );
449 mBlueContrastEnhancement->writeXml( doc, blueContrastElem );
450 rasterRendererElem.appendChild( blueContrastElem );
452 parentElem.appendChild( rasterRendererElem );
458 if ( mRedBand != -1 )
460 bandList << mRedBand;
462 if ( mGreenBand != -1 )
464 bandList << mGreenBand;
466 if ( mBlueBand != -1 )
468 bandList << mBlueBand;
475 QList<QgsLayerTreeModelLegendNode *> res;
476 if ( mRedBand != -1 )
480 if ( mGreenBand != -1 )
484 if ( mBlueBand != -1 )
496 toSld( doc, element, context );
514 bool isDefaultCombination =
true;
515 QList<int> defaultBandCombination( { 1, 2, 3 } );
517 isDefaultCombination = isDefaultCombination && (
usesBands() == defaultBandCombination );
518 isDefaultCombination = isDefaultCombination && (
524 if ( isDefaultCombination )
527 isDefaultCombination = isDefaultCombination && (
528 ( mRedContrastEnhancement->minimumValue() == statRed.
minimumValue &&
529 mRedContrastEnhancement->maximumValue() == statRed.
maximumValue )
532 if ( isDefaultCombination )
535 isDefaultCombination = isDefaultCombination && (
536 ( mGreenContrastEnhancement->minimumValue() == statGreen.
minimumValue &&
537 mGreenContrastEnhancement->maximumValue() == statGreen.
maximumValue )
540 if ( isDefaultCombination )
543 isDefaultCombination = isDefaultCombination && (
544 ( mBlueContrastEnhancement->minimumValue() == statBlue.
minimumValue &&
545 mBlueContrastEnhancement->maximumValue() == statBlue.
maximumValue )
548 if ( isDefaultCombination )
553 QDomNodeList elements = element.elementsByTagName( QStringLiteral(
"sld:RasterSymbolizer" ) );
554 if ( elements.size() == 0 )
558 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
563 QDomElement channelSelectionElem = doc.createElement( QStringLiteral(
"sld:ChannelSelection" ) );
564 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Opacity" ) );
565 if ( elements.size() != 0 )
567 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
571 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Geometry" ) );
572 if ( elements.size() != 0 )
574 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
578 rasterSymbolizerElem.insertBefore( channelSelectionElem, rasterSymbolizerElem.firstChild() );
583 static QStringList tags { QStringLiteral(
"sld:RedChannel" ), QStringLiteral(
"sld:GreenChannel" ), QStringLiteral(
"sld:BlueChannel" ) };
585 QList<QgsContrastEnhancement *> contrastEnhancements;
586 contrastEnhancements.append( mRedContrastEnhancement.get() );
587 contrastEnhancements.append( mGreenContrastEnhancement.get() );
588 contrastEnhancements.append( mBlueContrastEnhancement.get() );
591 QList<int>::const_iterator bandIt = bands.constBegin();
592 for (
int tagCounter = 0 ; bandIt != bands.constEnd(); ++bandIt, ++tagCounter )
597 QDomElement channelElem = doc.createElement( tags[ tagCounter ] );
598 channelSelectionElem.appendChild( channelElem );
601 QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral(
"sld:SourceChannelName" ) );
602 sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( *bandIt ) ) );
603 channelElem.appendChild( sourceChannelNameElem );
608 if ( contrastEnhancements[ tagCounter ] )
610 QDomElement contrastEnhancementElem = doc.createElement( QStringLiteral(
"sld:ContrastEnhancement" ) );
611 contrastEnhancements[ tagCounter ]->toSld( doc, contrastEnhancementElem );
612 channelElem.appendChild( contrastEnhancementElem );
625 bool refreshed =
false;
626 if ( min.size() >= 3 && max.size() >= 3 )
631 !std::isnan( min[0] ) && !std::isnan( max[0] ) )
633 mRedContrastEnhancement->setMinimumValue( min[0] );
634 mRedContrastEnhancement->setMaximumValue( max[0] );
639 !std::isnan( min[1] ) && !std::isnan( max[1] ) )
641 mGreenContrastEnhancement->setMinimumValue( min[1] );
642 mGreenContrastEnhancement->setMaximumValue( max[1] );
647 !std::isnan( min[2] ) && !std::isnan( max[2] ) )
649 mBlueContrastEnhancement->setMinimumValue( min[2] );
650 mBlueContrastEnhancement->setMaximumValue( max[2] );
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.
@ Byte
Eight bit unsigned integer (quint8)
Handles contrast enhancement and clipping.
@ StretchToMinimumMaximum
Linear histogram.
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
void readXml(const QDomElement &elem)
Layer tree node points to a map layer.
Renderer for multiband images with the color components.
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.
QgsMultiBandColorRenderer(QgsRasterInterface *input, int redBand, int greenBand, int blueBand, QgsContrastEnhancement *redEnhancement=nullptr, QgsContrastEnhancement *greenEnhancement=nullptr, QgsContrastEnhancement *blueEnhancement=nullptr)
Constructor for QgsMultiBandColorRenderer.
const QgsContrastEnhancement * greenContrastEnhancement() const
Returns the contrast enhancement to use for the green channel.
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
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.
Qgis::RasterRendererFlags flags() const override
Returns flags which dictate renderer behavior.
int blueBand() const
Returns the band number for the blue channel.
~QgsMultiBandColorRenderer() override
const QgsContrastEnhancement * blueContrastEnhancement() const
Returns the contrast enhancement to use for the blue channel.
void setGreenContrastEnhancement(QgsContrastEnhancement *ce)
Sets the contrast enhancement to use for the green channel.
QList< int > usesBands() const override
Returns a list of band numbers used by the renderer.
QgsMultiBandColorRenderer * clone() const override
Clone itself, create deep copy.
void setBlueContrastEnhancement(QgsContrastEnhancement *ce)
Sets the contrast enhancement to use for the blue channel.
static QgsRasterRenderer * create(const QDomElement &elem, QgsRasterInterface *input)
void setRedContrastEnhancement(QgsContrastEnhancement *ce)
Sets the contrast enhancement to use for the red channel.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
const QgsContrastEnhancement * redContrastEnhancement() const
Returns the contrast enhancement to use for the red channel.
int redBand() const
Returns the band number for the red channel.
QList< QgsLayerTreeModelLegendNode * > createLegendNodes(QgsLayerTreeLayer *nodeLayer) override
Creates a set of legend nodes representing the renderer.
int greenBand() const
Returns the band number for the green channel.
The RasterBandStats struct is a container for statistics about a single raster band.
double minimumValue
The minimum cell value in the raster band.
double maximumValue
The maximum cell value in the raster band.
Feedback object tailored for raster block reading.
double value(int row, int column) const
Read a single value if type of block is numeric.
double valueAndNoData(int row, int column, bool &isNoData) const
Reads a single value from the pixel at row and column, if type of block is numeric.
bool isNoData(int row, int column) const
Checks if value at position is no data.
Qgis::DataType dataType() const
Returns data type.
const quint8 * byteData() const
Gives direct access to the raster block data.
Base class for processing filters like renderers, reprojector, resampler etc.
virtual QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr)=0
Read block of data using given extent and size.
virtual Qgis::DataType dataType(int bandNo) const =0
Returns data type for the band specified by number.
Q_DECL_DEPRECATED QgsRasterBandStats bandStatistics(int bandNo, int stats, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
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.
Raster renderer pipe that applies colors to a raster.
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.
void _writeXml(QDomDocument &doc, QDomElement &rasterRendererElem) const
Write upper class info into rasterrenderer element (called by writeXml method of subclasses)
QgsRasterTransparency * mRasterTransparency
Raster transparency per color or value. Overwrites global alpha value.
bool usesTransparency() const
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.
Implementation of legend node interface for displaying raster legend entries.
double opacityForRgbValues(double redValue, double greenValue, double blueValue) const
Returns the opacity (as a value from 0 to 1) for a set of RGB pixel values.
A rectangle specified with double values.
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 QgsDebugError(str)