23#include <QDomDocument>
34 , mGreenBand( greenBand )
35 , mBlueBand( blueBand )
36 , mRedContrastEnhancement( redEnhancement )
37 , mGreenContrastEnhancement( greenEnhancement )
38 , mBlueContrastEnhancement( blueEnhancement )
44 delete mRedContrastEnhancement;
45 delete mGreenContrastEnhancement;
46 delete mBlueContrastEnhancement;
54 if ( mRedContrastEnhancement )
58 if ( mGreenContrastEnhancement )
62 if ( mBlueContrastEnhancement )
77 delete mRedContrastEnhancement;
78 mRedContrastEnhancement = ce;
83 delete mGreenContrastEnhancement;
84 mGreenContrastEnhancement = ce;
89 delete mBlueContrastEnhancement;
90 mBlueContrastEnhancement = ce;
101 const int redBand = elem.attribute( QStringLiteral(
"redBand" ), QStringLiteral(
"-1" ) ).toInt();
102 const int greenBand = elem.attribute( QStringLiteral(
"greenBand" ), QStringLiteral(
"-1" ) ).toInt();
103 const int blueBand = elem.attribute( QStringLiteral(
"blueBand" ), QStringLiteral(
"-1" ) ).toInt();
107 const QDomElement redContrastElem = elem.firstChildElement( QStringLiteral(
"redContrastEnhancement" ) );
108 if ( !redContrastElem.isNull() )
116 const QDomElement greenContrastElem = elem.firstChildElement( QStringLiteral(
"greenContrastEnhancement" ) );
117 if ( !greenContrastElem.isNull() )
125 const QDomElement blueContrastElem = elem.firstChildElement( QStringLiteral(
"blueContrastEnhancement" ) );
126 if ( !blueContrastElem.isNull() )
142 std::unique_ptr< QgsRasterBlock > outputBlock(
new QgsRasterBlock() );
145 return outputBlock.release();
150 && mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
158 if ( mGreenBand > 0 )
170 return outputBlock.release();
178 QMap<int, QgsRasterBlock *> bandBlocks;
180 QList<int>::const_iterator bandIt = bands.constBegin();
181 for ( ; bandIt != bands.constEnd(); ++bandIt )
183 bandBlocks.insert( *bandIt, defaultPointer );
191 bandIt = bands.constBegin();
192 for ( ; bandIt != bands.constEnd(); ++bandIt )
195 if ( !bandBlocks[*bandIt] )
200 for ( ; bandIt != bands.constBegin(); --bandIt )
202 delete bandBlocks[*bandIt];
204 return outputBlock.release();
210 redBlock = bandBlocks[mRedBand];
212 if ( mGreenBand > 0 )
214 greenBlock = bandBlocks[mGreenBand];
218 blueBlock = bandBlocks[mBlueBand];
227 for (
int i = 0; i < bandBlocks.size(); i++ )
229 delete bandBlocks.
value( i );
231 return outputBlock.release();
234 QRgb *outputBlockColorData = outputBlock->colorData();
238 const quint8 *redData =
nullptr, *greenData =
nullptr, *blueData =
nullptr;
263 hasEnhancement = mRedContrastEnhancement || mGreenContrastEnhancement || mBlueContrastEnhancement;
265 if ( hasEnhancement )
270 for (
qgssize i = 0; i < count; i++ )
280 outputBlock->setColor( i, myDefaultColor );
284 outputBlockColorData[i] = qRgb( redData[i], greenData[i], blueData[i] );
289 bool redIsNoData =
false;
290 bool greenIsNoData =
false;
291 bool blueIsNoData =
false;
301 if ( !redIsNoData && !greenIsNoData )
308 outputBlock->setColor( i, myDefaultColor );
312 outputBlockColorData[i] = qRgb( redVal, greenVal, blueVal );
318 bool isNoData =
false;
326 if ( !isNoData && mGreenBand > 0 )
330 if ( !isNoData && mBlueBand > 0 )
336 outputBlock->setColor( i, myDefaultColor );
345 outputBlock->setColor( i, myDefaultColor );
350 if ( mRedContrastEnhancement )
354 if ( mGreenContrastEnhancement )
358 if ( mBlueContrastEnhancement )
371 const double alpha = alphaBlock->
value( i );
374 outputBlock->setColor( i, myDefaultColor );
379 currentOpacity *= alpha / 255.0;
385 outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
389 outputBlock->setColor( i, qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 ) );
394 QMap<int, QgsRasterBlock *>::const_iterator bandDelIt = bandBlocks.constBegin();
395 for ( ; bandDelIt != bandBlocks.constEnd(); ++bandDelIt )
397 delete bandDelIt.value();
400 return outputBlock.release();
405 if ( parentElem.isNull() )
410 QDomElement rasterRendererElem = doc.createElement( QStringLiteral(
"rasterrenderer" ) );
412 rasterRendererElem.setAttribute( QStringLiteral(
"redBand" ), mRedBand );
413 rasterRendererElem.setAttribute( QStringLiteral(
"greenBand" ), mGreenBand );
414 rasterRendererElem.setAttribute( QStringLiteral(
"blueBand" ), mBlueBand );
417 if ( mRedContrastEnhancement )
419 QDomElement redContrastElem = doc.createElement( QStringLiteral(
"redContrastEnhancement" ) );
420 mRedContrastEnhancement->
writeXml( doc, redContrastElem );
421 rasterRendererElem.appendChild( redContrastElem );
423 if ( mGreenContrastEnhancement )
425 QDomElement greenContrastElem = doc.createElement( QStringLiteral(
"greenContrastEnhancement" ) );
426 mGreenContrastEnhancement->
writeXml( doc, greenContrastElem );
427 rasterRendererElem.appendChild( greenContrastElem );
429 if ( mBlueContrastEnhancement )
431 QDomElement blueContrastElem = doc.createElement( QStringLiteral(
"blueContrastEnhancement" ) );
432 mBlueContrastEnhancement->
writeXml( doc, blueContrastElem );
433 rasterRendererElem.appendChild( blueContrastElem );
435 parentElem.appendChild( rasterRendererElem );
441 if ( mRedBand != -1 )
443 bandList << mRedBand;
445 if ( mGreenBand != -1 )
447 bandList << mGreenBand;
449 if ( mBlueBand != -1 )
451 bandList << mBlueBand;
458 QList<QgsLayerTreeModelLegendNode *> res;
459 if ( mRedBand != -1 )
463 if ( mGreenBand != -1 )
467 if ( mBlueBand != -1 )
490 bool isDefaultCombination =
true;
491 QList<int> defaultBandCombination( { 1, 2, 3 } );
493 isDefaultCombination = isDefaultCombination && (
usesBands() == defaultBandCombination );
494 isDefaultCombination = isDefaultCombination && (
500 if ( isDefaultCombination )
503 isDefaultCombination = isDefaultCombination && (
508 if ( isDefaultCombination )
511 isDefaultCombination = isDefaultCombination && (
516 if ( isDefaultCombination )
519 isDefaultCombination = isDefaultCombination && (
524 if ( isDefaultCombination )
529 QDomNodeList elements = element.elementsByTagName( QStringLiteral(
"sld:RasterSymbolizer" ) );
530 if ( elements.size() == 0 )
534 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
539 QDomElement channelSelectionElem = doc.createElement( QStringLiteral(
"sld:ChannelSelection" ) );
540 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Opacity" ) );
541 if ( elements.size() != 0 )
543 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
547 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Geometry" ) );
548 if ( elements.size() != 0 )
550 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
554 rasterSymbolizerElem.insertBefore( channelSelectionElem, rasterSymbolizerElem.firstChild() );
559 static QStringList tags { QStringLiteral(
"sld:RedChannel" ), QStringLiteral(
"sld:GreenChannel" ), QStringLiteral(
"sld:BlueChannel" ) };
561 QList<QgsContrastEnhancement *> contrastEnhancements;
562 contrastEnhancements.append( mRedContrastEnhancement );
563 contrastEnhancements.append( mGreenContrastEnhancement );
564 contrastEnhancements.append( mBlueContrastEnhancement );
567 QList<int>::const_iterator bandIt = bands.constBegin();
568 for (
int tagCounter = 0 ; bandIt != bands.constEnd(); ++bandIt, ++tagCounter )
573 QDomElement channelElem = doc.createElement( tags[ tagCounter ] );
574 channelSelectionElem.appendChild( channelElem );
577 QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral(
"sld:SourceChannelName" ) );
578 sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( *bandIt ) ) );
579 channelElem.appendChild( sourceChannelNameElem );
584 if ( contrastEnhancements[ tagCounter ] )
586 QDomElement contrastEnhancementElem = doc.createElement( QStringLiteral(
"sld:ContrastEnhancement" ) );
587 contrastEnhancements[ tagCounter ]->toSld( doc, contrastEnhancementElem );
588 channelElem.appendChild( contrastEnhancementElem );
600 bool refreshed =
false;
601 if ( min.size() >= 3 && max.size() >= 3 )
606 !std::isnan( min[0] ) && !std::isnan( max[0] ) )
614 !std::isnan( min[1] ) && !std::isnan( max[1] ) )
622 !std::isnan( min[2] ) && !std::isnan( 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)
Manipulates raster or point cloud pixel values so that they enhanceContrast or clip into a specified ...
@ StretchToMinimumMaximum
Linear histogram.
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
void setMinimumValue(double value, bool generateTable=true)
Sets the minimum value for the contrast enhancement range.
bool isValueInDisplayableRange(double value)
Returns true if a pixel value is in displayable range, false if pixel is outside of range (i....
int enhanceContrast(double value)
Applies the contrast enhancement to a value.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const
void readXml(const QDomElement &elem)
double minimumValue() const
Returns the minimum value for the contrast enhancement range.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
void setMaximumValue(double value, bool generateTable=true)
Sets the maximum value for the contrast enhancement range.
double maximumValue() const
Returns the maximum value for the contrast enhancement range.
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)
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.
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.
~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.
QList< QgsLayerTreeModelLegendNode * > createLegendNodes(QgsLayerTreeLayer *nodeLayer) override
Creates a set of legend nodes representing the renderer.
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 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.
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)