25#include <QDomDocument>
36 , mGreenBand( greenBand )
37 , mBlueBand( blueBand )
38 , mRedContrastEnhancement( redEnhancement )
39 , mGreenContrastEnhancement( greenEnhancement )
40 , mBlueContrastEnhancement( blueEnhancement )
46 delete mRedContrastEnhancement;
47 delete mGreenContrastEnhancement;
48 delete mBlueContrastEnhancement;
56 if ( mRedContrastEnhancement )
60 if ( mGreenContrastEnhancement )
64 if ( mBlueContrastEnhancement )
79 delete mRedContrastEnhancement;
80 mRedContrastEnhancement = ce;
85 delete mGreenContrastEnhancement;
86 mGreenContrastEnhancement = ce;
91 delete mBlueContrastEnhancement;
92 mBlueContrastEnhancement = ce;
103 const int redBand = elem.attribute( QStringLiteral(
"redBand" ), QStringLiteral(
"-1" ) ).toInt();
104 const int greenBand = elem.attribute( QStringLiteral(
"greenBand" ), QStringLiteral(
"-1" ) ).toInt();
105 const int blueBand = elem.attribute( QStringLiteral(
"blueBand" ), QStringLiteral(
"-1" ) ).toInt();
109 const QDomElement redContrastElem = elem.firstChildElement( QStringLiteral(
"redContrastEnhancement" ) );
110 if ( !redContrastElem.isNull() )
118 const QDomElement greenContrastElem = elem.firstChildElement( QStringLiteral(
"greenContrastEnhancement" ) );
119 if ( !greenContrastElem.isNull() )
127 const QDomElement blueContrastElem = elem.firstChildElement( QStringLiteral(
"blueContrastEnhancement" ) );
128 if ( !blueContrastElem.isNull() )
144 std::unique_ptr< QgsRasterBlock > outputBlock(
new QgsRasterBlock() );
147 return outputBlock.release();
152 && mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
160 if ( mGreenBand > 0 )
172 return outputBlock.release();
180 QMap<int, QgsRasterBlock *> bandBlocks;
182 QList<int>::const_iterator bandIt = bands.constBegin();
183 for ( ; bandIt != bands.constEnd(); ++bandIt )
185 bandBlocks.insert( *bandIt, defaultPointer );
193 bandIt = bands.constBegin();
194 for ( ; bandIt != bands.constEnd(); ++bandIt )
197 if ( !bandBlocks[*bandIt] )
202 for ( ; bandIt != bands.constBegin(); --bandIt )
204 delete bandBlocks[*bandIt];
206 return outputBlock.release();
212 redBlock = bandBlocks[mRedBand];
214 if ( mGreenBand > 0 )
216 greenBlock = bandBlocks[mGreenBand];
220 blueBlock = bandBlocks[mBlueBand];
229 for (
int i = 0; i < bandBlocks.size(); i++ )
231 delete bandBlocks.
value( i );
233 return outputBlock.release();
236 QRgb *outputBlockColorData = outputBlock->colorData();
240 const quint8 *redData =
nullptr, *greenData =
nullptr, *blueData =
nullptr;
265 hasEnhancement = mRedContrastEnhancement || mGreenContrastEnhancement || mBlueContrastEnhancement;
267 if ( hasEnhancement )
272 for (
qgssize i = 0; i < count; i++ )
282 outputBlock->setColor( i, myDefaultColor );
286 outputBlockColorData[i] = qRgb( redData[i], greenData[i], blueData[i] );
291 bool redIsNoData =
false;
292 bool greenIsNoData =
false;
293 bool blueIsNoData =
false;
303 if ( !redIsNoData && !greenIsNoData )
310 outputBlock->setColor( i, myDefaultColor );
314 outputBlockColorData[i] = qRgb( redVal, greenVal, blueVal );
320 bool isNoData =
false;
328 if ( !isNoData && mGreenBand > 0 )
332 if ( !isNoData && mBlueBand > 0 )
338 outputBlock->setColor( i, myDefaultColor );
347 outputBlock->setColor( i, myDefaultColor );
352 if ( mRedContrastEnhancement )
356 if ( mGreenContrastEnhancement )
360 if ( mBlueContrastEnhancement )
373 currentOpacity *= alphaBlock->
value( i ) / 255.0;
378 outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
382 outputBlock->setColor( i, qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 ) );
387 QMap<int, QgsRasterBlock *>::const_iterator bandDelIt = bandBlocks.constBegin();
388 for ( ; bandDelIt != bandBlocks.constEnd(); ++bandDelIt )
390 delete bandDelIt.value();
393 return outputBlock.release();
398 if ( parentElem.isNull() )
403 QDomElement rasterRendererElem = doc.createElement( QStringLiteral(
"rasterrenderer" ) );
405 rasterRendererElem.setAttribute( QStringLiteral(
"redBand" ), mRedBand );
406 rasterRendererElem.setAttribute( QStringLiteral(
"greenBand" ), mGreenBand );
407 rasterRendererElem.setAttribute( QStringLiteral(
"blueBand" ), mBlueBand );
410 if ( mRedContrastEnhancement )
412 QDomElement redContrastElem = doc.createElement( QStringLiteral(
"redContrastEnhancement" ) );
413 mRedContrastEnhancement->
writeXml( doc, redContrastElem );
414 rasterRendererElem.appendChild( redContrastElem );
416 if ( mGreenContrastEnhancement )
418 QDomElement greenContrastElem = doc.createElement( QStringLiteral(
"greenContrastEnhancement" ) );
419 mGreenContrastEnhancement->
writeXml( doc, greenContrastElem );
420 rasterRendererElem.appendChild( greenContrastElem );
422 if ( mBlueContrastEnhancement )
424 QDomElement blueContrastElem = doc.createElement( QStringLiteral(
"blueContrastEnhancement" ) );
425 mBlueContrastEnhancement->
writeXml( doc, blueContrastElem );
426 rasterRendererElem.appendChild( blueContrastElem );
428 parentElem.appendChild( rasterRendererElem );
434 if ( mRedBand != -1 )
436 bandList << mRedBand;
438 if ( mGreenBand != -1 )
440 bandList << mGreenBand;
442 if ( mBlueBand != -1 )
444 bandList << mBlueBand;
451 QList<QgsLayerTreeModelLegendNode *> res;
452 if ( mRedBand != -1 )
456 if ( mGreenBand != -1 )
460 if ( mBlueBand != -1 )
483 bool isDefaultCombination =
true;
484 QList<int> defaultBandCombination( { 1, 2, 3 } );
486 isDefaultCombination = isDefaultCombination && (
usesBands() == defaultBandCombination );
487 isDefaultCombination = isDefaultCombination && (
493 if ( isDefaultCombination )
496 isDefaultCombination = isDefaultCombination && (
501 if ( isDefaultCombination )
504 isDefaultCombination = isDefaultCombination && (
509 if ( isDefaultCombination )
512 isDefaultCombination = isDefaultCombination && (
517 if ( isDefaultCombination )
522 QDomNodeList elements = element.elementsByTagName( QStringLiteral(
"sld:RasterSymbolizer" ) );
523 if ( elements.size() == 0 )
527 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
532 QDomElement channelSelectionElem = doc.createElement( QStringLiteral(
"sld:ChannelSelection" ) );
533 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Opacity" ) );
534 if ( elements.size() != 0 )
536 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
540 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Geometry" ) );
541 if ( elements.size() != 0 )
543 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
547 rasterSymbolizerElem.insertBefore( channelSelectionElem, rasterSymbolizerElem.firstChild() );
552 static QStringList tags { QStringLiteral(
"sld:RedChannel" ), QStringLiteral(
"sld:GreenChannel" ), QStringLiteral(
"sld:BlueChannel" ) };
554 QList<QgsContrastEnhancement *> contrastEnhancements;
555 contrastEnhancements.append( mRedContrastEnhancement );
556 contrastEnhancements.append( mGreenContrastEnhancement );
557 contrastEnhancements.append( mBlueContrastEnhancement );
560 QList<int>::const_iterator bandIt = bands.constBegin();
561 for (
int tagCounter = 0 ; bandIt != bands.constEnd(); ++bandIt, ++tagCounter )
566 QDomElement channelElem = doc.createElement( tags[ tagCounter ] );
567 channelSelectionElem.appendChild( channelElem );
570 QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral(
"sld:SourceChannelName" ) );
571 sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( *bandIt ) ) );
572 channelElem.appendChild( sourceChannelNameElem );
577 if ( contrastEnhancements[ tagCounter ] )
579 QDomElement contrastEnhancementElem = doc.createElement( QStringLiteral(
"sld:ContrastEnhancement" ) );
580 contrastEnhancements[ tagCounter ]->toSld( doc, contrastEnhancementElem );
581 channelElem.appendChild( contrastEnhancementElem );
@ 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.
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
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.
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 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.
Qgis::DataType dataType() const SIP_HOLDGIL
Returns data type.
double value(int row, int column) const SIP_HOLDGIL
Read a single value if type of block is numeric.
const quint8 * byteData() const
Gives direct access to the raster block data.
bool isNoData(int row, int column) const SIP_HOLDGIL
Checks if value at position is no 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.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, 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.
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.
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.
int alphaValue(double value, int globalTransparency=255) const
Returns the transparency value for a single value pixel.
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)