24#include <QDomDocument> 
   35  , mGreenBand( greenBand )
 
   36  , mBlueBand( blueBand )
 
   37  , mRedContrastEnhancement( redEnhancement )
 
   38  , mGreenContrastEnhancement( greenEnhancement )
 
   39  , mBlueContrastEnhancement( blueEnhancement )
 
 
   50  if ( mRedContrastEnhancement )
 
   54  if ( mGreenContrastEnhancement )
 
   58  if ( mBlueContrastEnhancement )
 
 
   73  if ( ce == mRedContrastEnhancement.get() )
 
   76  mRedContrastEnhancement.reset( ce );
 
 
   81  return mGreenContrastEnhancement.get();
 
 
   86  if ( ce == mGreenContrastEnhancement.get() )
 
   89  mGreenContrastEnhancement.reset( ce );
 
 
   94  return mBlueContrastEnhancement.get();
 
 
   99  if ( ce == mBlueContrastEnhancement.get() )
 
  102  mBlueContrastEnhancement.reset( ce );
 
 
  113  const int redBand = elem.attribute( QStringLiteral( 
"redBand" ), QStringLiteral( 
"-1" ) ).toInt();
 
  114  const int greenBand = elem.attribute( QStringLiteral( 
"greenBand" ), QStringLiteral( 
"-1" ) ).toInt();
 
  115  const int blueBand = elem.attribute( QStringLiteral( 
"blueBand" ), QStringLiteral( 
"-1" ) ).toInt();
 
  119  const QDomElement redContrastElem = elem.firstChildElement( QStringLiteral( 
"redContrastEnhancement" ) );
 
  120  if ( !redContrastElem.isNull() )
 
  128  const QDomElement greenContrastElem = elem.firstChildElement( QStringLiteral( 
"greenContrastEnhancement" ) );
 
  129  if ( !greenContrastElem.isNull() )
 
  137  const QDomElement blueContrastElem = elem.firstChildElement( QStringLiteral( 
"blueContrastEnhancement" ) );
 
  138  if ( !blueContrastElem.isNull() )
 
 
  154  auto outputBlock = std::make_unique<QgsRasterBlock>();
 
  157    return outputBlock.release();
 
  162                    && mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
 
  170  if ( mGreenBand > 0 )
 
  182    return outputBlock.release();
 
  190  QMap<int, QgsRasterBlock *> bandBlocks;
 
  192  QList<int>::const_iterator bandIt = bands.constBegin();
 
  193  for ( ; bandIt != bands.constEnd(); ++bandIt )
 
  195    bandBlocks.insert( *bandIt, defaultPointer );
 
  203  bandIt = bands.constBegin();
 
  204  for ( ; bandIt != bands.constEnd(); ++bandIt )
 
  207    if ( !bandBlocks[*bandIt] )
 
  212      for ( ; bandIt != bands.constBegin(); --bandIt )
 
  214        delete bandBlocks[*bandIt];
 
  216      return outputBlock.release();
 
  222    redBlock = bandBlocks[mRedBand];
 
  224  if ( mGreenBand > 0 )
 
  226    greenBlock = bandBlocks[mGreenBand];
 
  230    blueBlock = bandBlocks[mBlueBand];
 
  239    for ( 
int i = 0; i < bandBlocks.size(); i++ )
 
  241      delete bandBlocks.
value( i );
 
  243    return outputBlock.release();
 
  246  QRgb *outputBlockColorData = outputBlock->colorData();
 
  250  const quint8 *redData = 
nullptr, *greenData = 
nullptr, *blueData = 
nullptr;
 
  275      hasEnhancement = mRedContrastEnhancement || mGreenContrastEnhancement || mBlueContrastEnhancement;
 
  277    if ( hasEnhancement )
 
  282  for ( 
qgssize i = 0; i < count; i++ )
 
  292          outputBlock->setColor( i, myDefaultColor );
 
  296          outputBlockColorData[i] = qRgb( redData[i], greenData[i], blueData[i] );
 
  301        bool redIsNoData = 
false;
 
  302        bool greenIsNoData = 
false;
 
  303        bool blueIsNoData = 
false;
 
  313        if ( !redIsNoData && !greenIsNoData )
 
  320          outputBlock->setColor( i, myDefaultColor );
 
  324          outputBlockColorData[i] = qRgb( redVal, greenVal, blueVal );
 
  330    bool isNoData = 
false;
 
  338    if ( !isNoData && mGreenBand > 0 )
 
  342    if ( !isNoData && mBlueBand > 0 )
 
  348      outputBlock->setColor( i, myDefaultColor );
 
  353    if ( ( mRedContrastEnhancement && !mRedContrastEnhancement->isValueInDisplayableRange( redVal ) )
 
  354         || ( mGreenContrastEnhancement && !mGreenContrastEnhancement->isValueInDisplayableRange( redVal ) )
 
  355         || ( mBlueContrastEnhancement && !mBlueContrastEnhancement->isValueInDisplayableRange( redVal ) ) )
 
  357      outputBlock->setColor( i, myDefaultColor );
 
  362    if ( mRedContrastEnhancement )
 
  364      redVal = mRedContrastEnhancement->enhanceContrast( redVal );
 
  366    if ( mGreenContrastEnhancement )
 
  368      greenVal = mGreenContrastEnhancement->enhanceContrast( greenVal );
 
  370    if ( mBlueContrastEnhancement )
 
  372      blueVal = mBlueContrastEnhancement->enhanceContrast( blueVal );
 
  383      const double alpha = alphaBlock->
value( i );
 
  386        outputBlock->setColor( i, myDefaultColor );
 
  391        currentOpacity *= alpha / 255.0;
 
  397      outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
 
  401      outputBlock->setColor( i, qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 ) );
 
  406  QMap<int, QgsRasterBlock *>::const_iterator bandDelIt = bandBlocks.constBegin();
 
  407  for ( ; bandDelIt != bandBlocks.constEnd(); ++bandDelIt )
 
  409    delete bandDelIt.value();
 
  412  return outputBlock.release();
 
 
  417  return mRedContrastEnhancement.get();
 
 
  422  if ( parentElem.isNull() )
 
  427  QDomElement rasterRendererElem = doc.createElement( QStringLiteral( 
"rasterrenderer" ) );
 
  429  rasterRendererElem.setAttribute( QStringLiteral( 
"redBand" ), mRedBand );
 
  430  rasterRendererElem.setAttribute( QStringLiteral( 
"greenBand" ), mGreenBand );
 
  431  rasterRendererElem.setAttribute( QStringLiteral( 
"blueBand" ), mBlueBand );
 
  434  if ( mRedContrastEnhancement )
 
  436    QDomElement redContrastElem = doc.createElement( QStringLiteral( 
"redContrastEnhancement" ) );
 
  437    mRedContrastEnhancement->writeXml( doc, redContrastElem );
 
  438    rasterRendererElem.appendChild( redContrastElem );
 
  440  if ( mGreenContrastEnhancement )
 
  442    QDomElement greenContrastElem = doc.createElement( QStringLiteral( 
"greenContrastEnhancement" ) );
 
  443    mGreenContrastEnhancement->writeXml( doc, greenContrastElem );
 
  444    rasterRendererElem.appendChild( greenContrastElem );
 
  446  if ( mBlueContrastEnhancement )
 
  448    QDomElement blueContrastElem = doc.createElement( QStringLiteral( 
"blueContrastEnhancement" ) );
 
  449    mBlueContrastEnhancement->writeXml( doc, blueContrastElem );
 
  450    rasterRendererElem.appendChild( blueContrastElem );
 
  452  parentElem.appendChild( rasterRendererElem );
 
 
  458  if ( mRedBand != -1 )
 
  460    bandList << mRedBand;
 
  462  if ( mGreenBand != -1 )
 
  464    bandList << mGreenBand;
 
  466  if ( mBlueBand != -1 )
 
  468    bandList << mBlueBand;
 
 
  475  QList<QgsLayerTreeModelLegendNode *> res;
 
  476  if ( mRedBand != -1 )
 
  480  if ( mGreenBand != -1 )
 
  484  if ( mBlueBand != -1 )
 
 
  496  toSld( doc, element, context );
 
 
  514  bool isDefaultCombination = 
true;
 
  515  QList<int> defaultBandCombination( { 1, 2, 3 } );
 
  517  isDefaultCombination = isDefaultCombination && ( 
usesBands() == defaultBandCombination );
 
  518  isDefaultCombination = isDefaultCombination && (
 
  524  if ( isDefaultCombination )
 
  527    isDefaultCombination = isDefaultCombination && (
 
  528                             ( mRedContrastEnhancement->minimumValue() == statRed.
minimumValue &&
 
  529                               mRedContrastEnhancement->maximumValue() == statRed.
maximumValue )
 
  532  if ( isDefaultCombination )
 
  535    isDefaultCombination = isDefaultCombination && (
 
  536                             ( mGreenContrastEnhancement->minimumValue() == statGreen.
minimumValue &&
 
  537                               mGreenContrastEnhancement->maximumValue() == statGreen.
maximumValue )
 
  540  if ( isDefaultCombination )
 
  543    isDefaultCombination = isDefaultCombination && (
 
  544                             ( mBlueContrastEnhancement->minimumValue() == statBlue.
minimumValue &&
 
  545                               mBlueContrastEnhancement->maximumValue() == statBlue.
maximumValue )
 
  548  if ( isDefaultCombination )
 
  553  QDomNodeList elements = element.elementsByTagName( QStringLiteral( 
"sld:RasterSymbolizer" ) );
 
  554  if ( elements.size() == 0 )
 
  558  QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
 
  563  QDomElement channelSelectionElem = doc.createElement( QStringLiteral( 
"sld:ChannelSelection" ) );
 
  564  elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral( 
"sld:Opacity" ) );
 
  565  if ( elements.size() != 0 )
 
  567    rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
 
  571    elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral( 
"sld:Geometry" ) );
 
  572    if ( elements.size() != 0 )
 
  574      rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
 
  578      rasterSymbolizerElem.insertBefore( channelSelectionElem, rasterSymbolizerElem.firstChild() );
 
  583  static QStringList tags { QStringLiteral( 
"sld:RedChannel" ), QStringLiteral( 
"sld:GreenChannel" ), QStringLiteral( 
"sld:BlueChannel" ) };
 
  585  QList<QgsContrastEnhancement *> contrastEnhancements;
 
  586  contrastEnhancements.append( mRedContrastEnhancement.get() );
 
  587  contrastEnhancements.append( mGreenContrastEnhancement.get() );
 
  588  contrastEnhancements.append( mBlueContrastEnhancement.get() );
 
  591  QList<int>::const_iterator bandIt = bands.constBegin();
 
  592  for ( 
int tagCounter = 0 ; bandIt != bands.constEnd(); ++bandIt, ++tagCounter )
 
  597    QDomElement channelElem = doc.createElement( tags[ tagCounter ] );
 
  598    channelSelectionElem.appendChild( channelElem );
 
  601    QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral( 
"sld:SourceChannelName" ) );
 
  602    sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( *bandIt ) ) );
 
  603    channelElem.appendChild( sourceChannelNameElem );
 
  608    if ( contrastEnhancements[ tagCounter ] )
 
  610      QDomElement contrastEnhancementElem = doc.createElement( QStringLiteral( 
"sld:ContrastEnhancement" ) );
 
  611      contrastEnhancements[ tagCounter ]->toSld( doc, contrastEnhancementElem );
 
  612      channelElem.appendChild( contrastEnhancementElem );
 
 
  625  bool refreshed = 
false;
 
  626  if ( min.size() >= 3 && max.size() >= 3 )
 
  631         !std::isnan( min[0] ) && !std::isnan( max[0] ) )
 
  633      mRedContrastEnhancement->setMinimumValue( min[0] );
 
  634      mRedContrastEnhancement->setMaximumValue( max[0] );
 
  639         !std::isnan( min[1] ) && !std::isnan( max[1] ) )
 
  641      mGreenContrastEnhancement->setMinimumValue( min[1] );
 
  642      mGreenContrastEnhancement->setMaximumValue( max[1] );
 
  647         !std::isnan( min[2] ) && !std::isnan( max[2] ) )
 
  649      mBlueContrastEnhancement->setMinimumValue( min[2] );
 
  650      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.
 
void readXml(const QDomElement &elem)
 
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)
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.
 
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.
 
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)