25 #include <QDomDocument>
26 #include <QDomElement>
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 )
74 delete mRedContrastEnhancement;
75 mRedContrastEnhancement = ce;
80 delete mGreenContrastEnhancement;
81 mGreenContrastEnhancement = ce;
86 delete mBlueContrastEnhancement;
87 mBlueContrastEnhancement = ce;
98 const int redBand = elem.attribute( QStringLiteral(
"redBand" ), QStringLiteral(
"-1" ) ).toInt();
99 const int greenBand = elem.attribute( QStringLiteral(
"greenBand" ), QStringLiteral(
"-1" ) ).toInt();
100 const int blueBand = elem.attribute( QStringLiteral(
"blueBand" ), QStringLiteral(
"-1" ) ).toInt();
104 const QDomElement redContrastElem = elem.firstChildElement( QStringLiteral(
"redContrastEnhancement" ) );
105 if ( !redContrastElem.isNull() )
113 const QDomElement greenContrastElem = elem.firstChildElement( QStringLiteral(
"greenContrastEnhancement" ) );
114 if ( !greenContrastElem.isNull() )
122 const QDomElement blueContrastElem = elem.firstChildElement( QStringLiteral(
"blueContrastEnhancement" ) );
123 if ( !blueContrastElem.isNull() )
139 std::unique_ptr< QgsRasterBlock > outputBlock(
new QgsRasterBlock() );
142 return outputBlock.release();
147 && mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
155 if ( mGreenBand > 0 )
167 return outputBlock.release();
175 QMap<int, QgsRasterBlock *> bandBlocks;
177 QList<int>::const_iterator bandIt = bands.constBegin();
178 for ( ; bandIt != bands.constEnd(); ++bandIt )
180 bandBlocks.insert( *bandIt, defaultPointer );
188 bandIt = bands.constBegin();
189 for ( ; bandIt != bands.constEnd(); ++bandIt )
192 if ( !bandBlocks[*bandIt] )
197 for ( ; bandIt != bands.constBegin(); --bandIt )
199 delete bandBlocks[*bandIt];
201 return outputBlock.release();
207 redBlock = bandBlocks[mRedBand];
209 if ( mGreenBand > 0 )
211 greenBlock = bandBlocks[mGreenBand];
215 blueBlock = bandBlocks[mBlueBand];
224 for (
int i = 0; i < bandBlocks.size(); i++ )
226 delete bandBlocks.
value( i );
228 return outputBlock.release();
231 QRgb *outputBlockColorData = outputBlock->colorData();
235 const quint8 *redData =
nullptr, *greenData =
nullptr, *blueData =
nullptr;
260 hasEnhancement = mRedContrastEnhancement || mGreenContrastEnhancement || mBlueContrastEnhancement;
262 if ( hasEnhancement )
267 for (
qgssize i = 0; i < count; i++ )
277 outputBlock->setColor( i, myDefaultColor );
281 outputBlockColorData[i] = qRgb( redData[i], greenData[i], blueData[i] );
286 bool redIsNoData =
false;
287 bool greenIsNoData =
false;
288 bool blueIsNoData =
false;
298 if ( !redIsNoData && !greenIsNoData )
305 outputBlock->setColor( i, myDefaultColor );
309 outputBlockColorData[i] = qRgb( redVal, greenVal, blueVal );
315 bool isNoData =
false;
323 if ( !isNoData && mGreenBand > 0 )
327 if ( !isNoData && mBlueBand > 0 )
333 outputBlock->setColor( i, myDefaultColor );
342 outputBlock->setColor( i, myDefaultColor );
347 if ( mRedContrastEnhancement )
351 if ( mGreenContrastEnhancement )
355 if ( mBlueContrastEnhancement )
368 currentOpacity *= alphaBlock->
value( i ) / 255.0;
373 outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
377 outputBlock->setColor( i, qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 ) );
382 QMap<int, QgsRasterBlock *>::const_iterator bandDelIt = bandBlocks.constBegin();
383 for ( ; bandDelIt != bandBlocks.constEnd(); ++bandDelIt )
385 delete bandDelIt.value();
388 return outputBlock.release();
393 if ( parentElem.isNull() )
398 QDomElement rasterRendererElem = doc.createElement( QStringLiteral(
"rasterrenderer" ) );
400 rasterRendererElem.setAttribute( QStringLiteral(
"redBand" ), mRedBand );
401 rasterRendererElem.setAttribute( QStringLiteral(
"greenBand" ), mGreenBand );
402 rasterRendererElem.setAttribute( QStringLiteral(
"blueBand" ), mBlueBand );
405 if ( mRedContrastEnhancement )
407 QDomElement redContrastElem = doc.createElement( QStringLiteral(
"redContrastEnhancement" ) );
408 mRedContrastEnhancement->
writeXml( doc, redContrastElem );
409 rasterRendererElem.appendChild( redContrastElem );
411 if ( mGreenContrastEnhancement )
413 QDomElement greenContrastElem = doc.createElement( QStringLiteral(
"greenContrastEnhancement" ) );
414 mGreenContrastEnhancement->
writeXml( doc, greenContrastElem );
415 rasterRendererElem.appendChild( greenContrastElem );
417 if ( mBlueContrastEnhancement )
419 QDomElement blueContrastElem = doc.createElement( QStringLiteral(
"blueContrastEnhancement" ) );
420 mBlueContrastEnhancement->
writeXml( doc, blueContrastElem );
421 rasterRendererElem.appendChild( blueContrastElem );
423 parentElem.appendChild( rasterRendererElem );
429 if ( mRedBand != -1 )
431 bandList << mRedBand;
433 if ( mGreenBand != -1 )
435 bandList << mGreenBand;
437 if ( mBlueBand != -1 )
439 bandList << mBlueBand;
446 QList<QgsLayerTreeModelLegendNode *> res;
447 if ( mRedBand != -1 )
451 if ( mGreenBand != -1 )
455 if ( mBlueBand != -1 )
478 bool isDefaultCombination =
true;
479 QList<int> defaultBandCombination( { 1, 2, 3 } );
481 isDefaultCombination = isDefaultCombination && (
usesBands() == defaultBandCombination );
482 isDefaultCombination = isDefaultCombination && (
488 if ( isDefaultCombination )
491 isDefaultCombination = isDefaultCombination && (
496 if ( isDefaultCombination )
499 isDefaultCombination = isDefaultCombination && (
504 if ( isDefaultCombination )
507 isDefaultCombination = isDefaultCombination && (
512 if ( isDefaultCombination )
517 QDomNodeList elements = element.elementsByTagName( QStringLiteral(
"sld:RasterSymbolizer" ) );
518 if ( elements.size() == 0 )
522 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
527 QDomElement channelSelectionElem = doc.createElement( QStringLiteral(
"sld:ChannelSelection" ) );
528 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Opacity" ) );
529 if ( elements.size() != 0 )
531 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
535 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Geometry" ) );
536 if ( elements.size() != 0 )
538 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
542 rasterSymbolizerElem.insertBefore( channelSelectionElem, rasterSymbolizerElem.firstChild() );
547 static QStringList tags { QStringLiteral(
"sld:RedChannel" ), QStringLiteral(
"sld:GreenChannel" ), QStringLiteral(
"sld:BlueChannel" ) };
549 QList<QgsContrastEnhancement *> contrastEnhancements;
550 contrastEnhancements.append( mRedContrastEnhancement );
551 contrastEnhancements.append( mGreenContrastEnhancement );
552 contrastEnhancements.append( mBlueContrastEnhancement );
555 QList<int>::const_iterator bandIt = bands.constBegin();
556 for (
int tagCounter = 0 ; bandIt != bands.constEnd(); ++bandIt, ++tagCounter )
561 QDomElement channelElem = doc.createElement( tags[ tagCounter ] );
562 channelSelectionElem.appendChild( channelElem );
565 QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral(
"sld:SourceChannelName" ) );
566 sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( *bandIt ) ) );
567 channelElem.appendChild( sourceChannelNameElem );
572 if ( contrastEnhancements[ tagCounter ] )
574 QDomElement contrastEnhancementElem = doc.createElement( QStringLiteral(
"sld:ContrastEnhancement" ) );
575 contrastEnhancements[ tagCounter ]->toSld( doc, contrastEnhancementElem );
576 channelElem.appendChild( contrastEnhancementElem );
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 * redContrastEnhancement() const
Returns the contrast enhancement to use for the red 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.
const QgsContrastEnhancement * blueContrastEnhancement() const
Returns the contrast enhancement to use for the blue channel.
~QgsMultiBandColorRenderer() override
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.
QList< QgsLayerTreeModelLegendNode * > createLegendNodes(QgsLayerTreeLayer *nodeLayer) override
Creates a set of legend nodes representing the renderer.
const QgsContrastEnhancement * greenContrastEnhancement() const
Returns the contrast enhancement to use 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.
const quint8 * byteData() const
Gives direct access to the raster block data.
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.
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 QgsRasterInterface * input() const
Current input.
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.
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)