25#include <QDomDocument>
38 , mRedContrastEnhancement( redEnhancement )
39 , mGreenContrastEnhancement( greenEnhancement )
40 , mBlueContrastEnhancement( blueEnhancement )
51 if ( mRedContrastEnhancement )
55 if ( mGreenContrastEnhancement )
59 if ( mBlueContrastEnhancement )
74 if ( ce == mRedContrastEnhancement.get() )
77 mRedContrastEnhancement.reset( ce );
82 return mGreenContrastEnhancement.get();
87 if ( ce == mGreenContrastEnhancement.get() )
90 mGreenContrastEnhancement.reset( ce );
95 return mBlueContrastEnhancement.get();
100 if ( ce == mBlueContrastEnhancement.get() )
103 mBlueContrastEnhancement.reset( ce );
114 const int redBand = elem.attribute( QStringLiteral(
"redBand" ), QStringLiteral(
"-1" ) ).toInt();
115 const int greenBand = elem.attribute( QStringLiteral(
"greenBand" ), QStringLiteral(
"-1" ) ).toInt();
116 const int blueBand = elem.attribute( QStringLiteral(
"blueBand" ), QStringLiteral(
"-1" ) ).toInt();
120 const QDomElement redContrastElem = elem.firstChildElement( QStringLiteral(
"redContrastEnhancement" ) );
121 if ( !redContrastElem.isNull() )
129 const QDomElement greenContrastElem = elem.firstChildElement( QStringLiteral(
"greenContrastEnhancement" ) );
130 if ( !greenContrastElem.isNull() )
138 const QDomElement blueContrastElem = elem.firstChildElement( QStringLiteral(
"blueContrastEnhancement" ) );
139 if ( !blueContrastElem.isNull() )
155 auto outputBlock = std::make_unique<QgsRasterBlock>();
158 return outputBlock.release();
163 && mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
171 if ( mGreenBand > 0 )
183 return outputBlock.release();
191 QMap<int, QgsRasterBlock *> bandBlocks;
193 QList<int>::const_iterator bandIt = bands.constBegin();
194 for ( ; bandIt != bands.constEnd(); ++bandIt )
196 bandBlocks.insert( *bandIt, defaultPointer );
204 bandIt = bands.constBegin();
205 for ( ; bandIt != bands.constEnd(); ++bandIt )
207 bandBlocks[*bandIt] =
mInput->block( *bandIt,
extent, width, height, feedback );
208 if ( !bandBlocks[*bandIt] )
213 for ( ; bandIt != bands.constBegin(); --bandIt )
215 delete bandBlocks[*bandIt];
217 return outputBlock.release();
223 redBlock = bandBlocks[mRedBand];
225 if ( mGreenBand > 0 )
227 greenBlock = bandBlocks[mGreenBand];
231 blueBlock = bandBlocks[mBlueBand];
240 for (
int i = 0; i < bandBlocks.size(); i++ )
242 delete bandBlocks.value( i );
244 return outputBlock.release();
247 QRgb *outputBlockColorData = outputBlock->colorData();
251 const quint8 *redData =
nullptr, *greenData =
nullptr, *blueData =
nullptr;
276 hasEnhancement = mRedContrastEnhancement || mGreenContrastEnhancement || mBlueContrastEnhancement;
278 if ( hasEnhancement )
283 for (
qgssize i = 0; i < count; i++ )
293 outputBlock->setColor( i, myDefaultColor );
297 outputBlockColorData[i] = qRgb( redData[i], greenData[i], blueData[i] );
302 bool redIsNoData =
false;
303 bool greenIsNoData =
false;
304 bool blueIsNoData =
false;
314 if ( !redIsNoData && !greenIsNoData )
321 outputBlock->setColor( i, myDefaultColor );
325 outputBlockColorData[i] = qRgb( redVal, greenVal, blueVal );
331 bool isNoData =
false;
339 if ( !isNoData && mGreenBand > 0 )
343 if ( !isNoData && mBlueBand > 0 )
349 outputBlock->setColor( i, myDefaultColor );
354 if ( ( mRedContrastEnhancement && !mRedContrastEnhancement->isValueInDisplayableRange( redVal ) )
355 || ( mGreenContrastEnhancement && !mGreenContrastEnhancement->isValueInDisplayableRange( redVal ) )
356 || ( mBlueContrastEnhancement && !mBlueContrastEnhancement->isValueInDisplayableRange( redVal ) ) )
358 outputBlock->setColor( i, myDefaultColor );
363 if ( mRedContrastEnhancement )
365 redVal = mRedContrastEnhancement->enhanceContrast( redVal );
367 if ( mGreenContrastEnhancement )
369 greenVal = mGreenContrastEnhancement->enhanceContrast( greenVal );
371 if ( mBlueContrastEnhancement )
373 blueVal = mBlueContrastEnhancement->enhanceContrast( blueVal );
384 const double alpha = alphaBlock->
value( i );
387 outputBlock->setColor( i, myDefaultColor );
392 currentOpacity *= alpha / 255.0;
398 outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
402 outputBlock->setColor( i, qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 ) );
407 QMap<int, QgsRasterBlock *>::const_iterator bandDelIt = bandBlocks.constBegin();
408 for ( ; bandDelIt != bandBlocks.constEnd(); ++bandDelIt )
410 delete bandDelIt.value();
413 return outputBlock.release();
418 return mRedContrastEnhancement.get();
423 if ( parentElem.isNull() )
428 QDomElement rasterRendererElem = doc.createElement( QStringLiteral(
"rasterrenderer" ) );
430 rasterRendererElem.setAttribute( QStringLiteral(
"redBand" ), mRedBand );
431 rasterRendererElem.setAttribute( QStringLiteral(
"greenBand" ), mGreenBand );
432 rasterRendererElem.setAttribute( QStringLiteral(
"blueBand" ), mBlueBand );
435 if ( mRedContrastEnhancement )
437 QDomElement redContrastElem = doc.createElement( QStringLiteral(
"redContrastEnhancement" ) );
438 mRedContrastEnhancement->writeXml( doc, redContrastElem );
439 rasterRendererElem.appendChild( redContrastElem );
441 if ( mGreenContrastEnhancement )
443 QDomElement greenContrastElem = doc.createElement( QStringLiteral(
"greenContrastEnhancement" ) );
444 mGreenContrastEnhancement->writeXml( doc, greenContrastElem );
445 rasterRendererElem.appendChild( greenContrastElem );
447 if ( mBlueContrastEnhancement )
449 QDomElement blueContrastElem = doc.createElement( QStringLiteral(
"blueContrastEnhancement" ) );
450 mBlueContrastEnhancement->writeXml( doc, blueContrastElem );
451 rasterRendererElem.appendChild( blueContrastElem );
453 parentElem.appendChild( rasterRendererElem );
459 if ( mRedBand != -1 )
461 bandList << mRedBand;
463 if ( mGreenBand != -1 )
465 bandList << mGreenBand;
467 if ( mBlueBand != -1 )
469 bandList << mBlueBand;
476 QList<QgsLayerTreeModelLegendNode *> res;
477 if ( mRedBand != -1 )
481 if ( mGreenBand != -1 )
485 if ( mBlueBand != -1 )
497 toSld( doc, element, context );
515 bool isDefaultCombination =
true;
516 QList<int> defaultBandCombination( { 1, 2, 3 } );
518 isDefaultCombination = isDefaultCombination && (
usesBands() == defaultBandCombination );
519 isDefaultCombination = isDefaultCombination && (
525 if ( isDefaultCombination )
528 isDefaultCombination = isDefaultCombination && (
529 ( mRedContrastEnhancement->minimumValue() == statRed.
minimumValue &&
530 mRedContrastEnhancement->maximumValue() == statRed.
maximumValue )
533 if ( isDefaultCombination )
536 isDefaultCombination = isDefaultCombination && (
537 ( mGreenContrastEnhancement->minimumValue() == statGreen.
minimumValue &&
538 mGreenContrastEnhancement->maximumValue() == statGreen.
maximumValue )
541 if ( isDefaultCombination )
544 isDefaultCombination = isDefaultCombination && (
545 ( mBlueContrastEnhancement->minimumValue() == statBlue.
minimumValue &&
546 mBlueContrastEnhancement->maximumValue() == statBlue.
maximumValue )
549 if ( isDefaultCombination )
554 QDomNodeList elements = element.elementsByTagName( QStringLiteral(
"sld:RasterSymbolizer" ) );
555 if ( elements.size() == 0 )
559 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
564 QDomElement channelSelectionElem = doc.createElement( QStringLiteral(
"sld:ChannelSelection" ) );
565 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Opacity" ) );
566 if ( elements.size() != 0 )
568 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
572 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Geometry" ) );
573 if ( elements.size() != 0 )
575 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
579 rasterSymbolizerElem.insertBefore( channelSelectionElem, rasterSymbolizerElem.firstChild() );
584 static QStringList tags { QStringLiteral(
"sld:RedChannel" ), QStringLiteral(
"sld:GreenChannel" ), QStringLiteral(
"sld:BlueChannel" ) };
586 QList<QgsContrastEnhancement *> contrastEnhancements;
587 contrastEnhancements.append( mRedContrastEnhancement.get() );
588 contrastEnhancements.append( mGreenContrastEnhancement.get() );
589 contrastEnhancements.append( mBlueContrastEnhancement.get() );
592 QList<int>::const_iterator bandIt = bands.constBegin();
593 for (
int tagCounter = 0 ; bandIt != bands.constEnd(); ++bandIt, ++tagCounter )
598 QDomElement channelElem = doc.createElement( tags[ tagCounter ] );
599 channelSelectionElem.appendChild( channelElem );
602 QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral(
"sld:SourceChannelName" ) );
603 sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( *bandIt ) ) );
604 channelElem.appendChild( sourceChannelNameElem );
609 if ( contrastEnhancements[ tagCounter ] )
611 QDomElement contrastEnhancementElem = doc.createElement( QStringLiteral(
"sld:ContrastEnhancement" ) );
612 contrastEnhancements[ tagCounter ]->toSld( doc, contrastEnhancementElem );
613 channelElem.appendChild( contrastEnhancementElem );
626 bool refreshed =
false;
627 if ( min.size() >= 3 && max.size() >= 3 )
632 !std::isnan( min[0] ) && !std::isnan( max[0] ) )
634 mRedContrastEnhancement->setMinimumValue( min[0] );
635 mRedContrastEnhancement->setMaximumValue( max[0] );
640 !std::isnan( min[1] ) && !std::isnan( max[1] ) )
642 mGreenContrastEnhancement->setMinimumValue( min[1] );
643 mGreenContrastEnhancement->setMaximumValue( max[1] );
648 !std::isnan( min[2] ) && !std::isnan( max[2] ) )
650 mBlueContrastEnhancement->setMinimumValue( min[2] );
651 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.
Layer tree node points to a map layer.
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.
QgsRasterInterface(QgsRasterInterface *input=nullptr)
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.
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).
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.
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)