24 #include <QDomDocument>
25 #include <QDomElement>
35 , mGreenBand( greenBand )
36 , mBlueBand( blueBand )
37 , mRedContrastEnhancement( redEnhancement )
38 , mGreenContrastEnhancement( greenEnhancement )
39 , mBlueContrastEnhancement( blueEnhancement )
45 delete mRedContrastEnhancement;
46 delete mGreenContrastEnhancement;
47 delete mBlueContrastEnhancement;
55 if ( mRedContrastEnhancement )
59 if ( mGreenContrastEnhancement )
63 if ( mBlueContrastEnhancement )
73 delete mRedContrastEnhancement;
74 mRedContrastEnhancement = ce;
79 delete mGreenContrastEnhancement;
80 mGreenContrastEnhancement = ce;
85 delete mBlueContrastEnhancement;
86 mBlueContrastEnhancement = ce;
97 int redBand = elem.attribute( QStringLiteral(
"redBand" ), QStringLiteral(
"-1" ) ).toInt();
98 int greenBand = elem.attribute( QStringLiteral(
"greenBand" ), QStringLiteral(
"-1" ) ).toInt();
99 int blueBand = elem.attribute( QStringLiteral(
"blueBand" ), QStringLiteral(
"-1" ) ).toInt();
103 QDomElement redContrastElem = elem.firstChildElement( QStringLiteral(
"redContrastEnhancement" ) );
104 if ( !redContrastElem.isNull() )
112 QDomElement greenContrastElem = elem.firstChildElement( QStringLiteral(
"greenContrastEnhancement" ) );
113 if ( !greenContrastElem.isNull() )
121 QDomElement blueContrastElem = elem.firstChildElement( QStringLiteral(
"blueContrastEnhancement" ) );
122 if ( !blueContrastElem.isNull() )
138 std::unique_ptr< QgsRasterBlock > outputBlock(
new QgsRasterBlock() );
141 return outputBlock.release();
146 && mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
154 if ( mGreenBand > 0 )
166 return outputBlock.release();
174 QMap<int, QgsRasterBlock *> bandBlocks;
176 QSet<int>::const_iterator bandIt = bands.constBegin();
177 for ( ; bandIt != bands.constEnd(); ++bandIt )
179 bandBlocks.insert( *bandIt, defaultPointer );
187 bandIt = bands.constBegin();
188 for ( ; bandIt != bands.constEnd(); ++bandIt )
191 if ( !bandBlocks[*bandIt] )
196 for ( ; bandIt != bands.constBegin(); --bandIt )
198 delete bandBlocks[*bandIt];
200 return outputBlock.release();
206 redBlock = bandBlocks[mRedBand];
208 if ( mGreenBand > 0 )
210 greenBlock = bandBlocks[mGreenBand];
214 blueBlock = bandBlocks[mBlueBand];
223 for (
int i = 0; i < bandBlocks.size(); i++ )
225 delete bandBlocks.
value( i );
227 return outputBlock.release();
230 QRgb *outputBlockColorData = outputBlock->colorData();
234 const quint8 *redData =
nullptr, *greenData =
nullptr, *blueData =
nullptr;
259 hasEnhancement = mRedContrastEnhancement || mGreenContrastEnhancement || mBlueContrastEnhancement;
261 if ( hasEnhancement )
266 for (
qgssize i = 0; i < count; i++ )
276 outputBlock->setColor( i, myDefaultColor );
280 outputBlockColorData[i] = qRgb( redData[i], greenData[i], blueData[i] );
285 bool redIsNoData =
false;
286 bool greenIsNoData =
false;
287 bool blueIsNoData =
false;
297 if ( !redIsNoData && !greenIsNoData )
304 outputBlock->setColor( i, myDefaultColor );
308 outputBlockColorData[i] = qRgb( redVal, greenVal, blueVal );
314 bool isNoData =
false;
322 if ( !isNoData && mGreenBand > 0 )
326 if ( !isNoData && mBlueBand > 0 )
332 outputBlock->setColor( i, myDefaultColor );
341 outputBlock->setColor( i, myDefaultColor );
346 if ( mRedContrastEnhancement )
350 if ( mGreenContrastEnhancement )
354 if ( mBlueContrastEnhancement )
367 currentOpacity *= alphaBlock->
value( i ) / 255.0;
372 outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
376 outputBlock->setColor( i, qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 ) );
381 QMap<int, QgsRasterBlock *>::const_iterator bandDelIt = bandBlocks.constBegin();
382 for ( ; bandDelIt != bandBlocks.constEnd(); ++bandDelIt )
384 delete bandDelIt.value();
387 return outputBlock.release();
392 if ( parentElem.isNull() )
397 QDomElement rasterRendererElem = doc.createElement( QStringLiteral(
"rasterrenderer" ) );
399 rasterRendererElem.setAttribute( QStringLiteral(
"redBand" ), mRedBand );
400 rasterRendererElem.setAttribute( QStringLiteral(
"greenBand" ), mGreenBand );
401 rasterRendererElem.setAttribute( QStringLiteral(
"blueBand" ), mBlueBand );
404 if ( mRedContrastEnhancement )
406 QDomElement redContrastElem = doc.createElement( QStringLiteral(
"redContrastEnhancement" ) );
407 mRedContrastEnhancement->
writeXml( doc, redContrastElem );
408 rasterRendererElem.appendChild( redContrastElem );
410 if ( mGreenContrastEnhancement )
412 QDomElement greenContrastElem = doc.createElement( QStringLiteral(
"greenContrastEnhancement" ) );
413 mGreenContrastEnhancement->
writeXml( doc, greenContrastElem );
414 rasterRendererElem.appendChild( greenContrastElem );
416 if ( mBlueContrastEnhancement )
418 QDomElement blueContrastElem = doc.createElement( QStringLiteral(
"blueContrastEnhancement" ) );
419 mBlueContrastEnhancement->
writeXml( doc, blueContrastElem );
420 rasterRendererElem.appendChild( blueContrastElem );
422 parentElem.appendChild( rasterRendererElem );
428 if ( mRedBand != -1 )
430 bandList << mRedBand;
432 if ( mGreenBand != -1 )
434 bandList << mGreenBand;
436 if ( mBlueBand != -1 )
438 bandList << mBlueBand;
445 QList<QgsLayerTreeModelLegendNode *> res;
446 if ( mRedBand != -1 )
450 if ( mGreenBand != -1 )
454 if ( mBlueBand != -1 )
477 bool isDefaultCombination =
true;
478 QList<int> defaultBandCombination( { 1, 2, 3 } );
480 isDefaultCombination = isDefaultCombination && (
usesBands() == defaultBandCombination );
481 isDefaultCombination = isDefaultCombination && (
487 if ( isDefaultCombination )
490 isDefaultCombination = isDefaultCombination && (
495 if ( isDefaultCombination )
498 isDefaultCombination = isDefaultCombination && (
503 if ( isDefaultCombination )
506 isDefaultCombination = isDefaultCombination && (
511 if ( isDefaultCombination )
516 QDomNodeList elements = element.elementsByTagName( QStringLiteral(
"sld:RasterSymbolizer" ) );
517 if ( elements.size() == 0 )
521 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
526 QDomElement channelSelectionElem = doc.createElement( QStringLiteral(
"sld:ChannelSelection" ) );
527 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Opacity" ) );
528 if ( elements.size() != 0 )
530 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
534 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral(
"sld:Geometry" ) );
535 if ( elements.size() != 0 )
537 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
541 rasterSymbolizerElem.insertBefore( channelSelectionElem, rasterSymbolizerElem.firstChild() );
546 static QStringList tags { QStringLiteral(
"sld:RedChannel" ), QStringLiteral(
"sld:GreenChannel" ), QStringLiteral(
"sld:BlueChannel" ) };
548 QList<QgsContrastEnhancement *> contrastEnhancements;
549 contrastEnhancements.append( mRedContrastEnhancement );
550 contrastEnhancements.append( mGreenContrastEnhancement );
551 contrastEnhancements.append( mBlueContrastEnhancement );
554 QList<int>::const_iterator bandIt = bands.constBegin();
555 for (
int tagCounter = 0 ; bandIt != bands.constEnd(); ++bandIt, ++tagCounter )
560 QDomElement channelElem = doc.createElement( tags[ tagCounter ] );
561 channelSelectionElem.appendChild( channelElem );
564 QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral(
"sld:SourceChannelName" ) );
565 sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( *bandIt ) ) );
566 channelElem.appendChild( sourceChannelNameElem );
571 if ( contrastEnhancements[ tagCounter ] )
573 QDomElement contrastEnhancementElem = doc.createElement( QStringLiteral(
"sld:ContrastEnhancement" ) );
574 contrastEnhancements[ tagCounter ]->toSld( doc, contrastEnhancementElem );
575 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)