QGIS API Documentation  3.37.0-Master (a5b4d9743e8)
qgsrasterrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterrenderer.cpp
3  ---------------------
4  begin : December 2011
5  copyright : (C) 2011 by Marco Hugentobler
6  email : marco at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsrasterrenderer.h"
19 #include "qgsrastertransparency.h"
20 
21 #include "qgscolorutils.h"
23 
24 #include <QCoreApplication>
25 #include <QDomDocument>
26 #include <QDomElement>
27 #include <QImage>
28 #include <QPainter>
29 
30 // See #9101 before any change of NODATA_COLOR!
31 const QRgb QgsRasterRenderer::NODATA_COLOR = qRgba( 0, 0, 0, 0 );
32 
34  : QgsRasterInterface( input )
35  , mType( type )
36 {
37 }
38 
40 {
41  delete mRasterTransparency;
42 }
43 
45 {
46  if ( mOn ) return 1;
47 
48  if ( mInput ) return mInput->bandCount();
49 
50  return 0;
51 }
52 
54 {
55  QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
56 
58 
59  if ( mInput ) return mInput->dataType( bandNo );
60 
62 }
63 
65 {
67 }
68 
70 {
71  return false;
72 }
73 
75 {
76  // Renderer can only work with numerical values in at least 1 band
77  if ( !input ) return false;
78 
79  if ( !mOn )
80  {
81  // In off mode we can connect to anything
82  mInput = input;
83  return true;
84  }
85 
86  for ( int i = 1; i <= input->bandCount(); i++ )
87  {
88  const Qgis::DataType bandType = input->dataType( i );
89  // we always allow unknown data types to connect - otherwise invalid layers cannot setup
90  // their original rendering pipe and this information is lost
91  if ( bandType != Qgis::DataType::UnknownDataType && !QgsRasterBlock::typeIsNumeric( bandType ) )
92  {
93  return false;
94  }
95  }
96  mInput = input;
97  return true;
98 }
99 
101 {
102  return -1;
103 }
104 
106 {
107  return false;
108 }
109 
111 {
112  if ( !mInput )
113  {
114  return true;
115  }
116  return ( mAlphaBand > 0 || ( mRasterTransparency && !mRasterTransparency->isEmpty() ) || !qgsDoubleNear( mOpacity, 1.0 ) );
117 }
118 
120 {
121  delete mRasterTransparency;
123 }
124 
125 QList< QPair< QString, QColor > > QgsRasterRenderer::legendSymbologyItems() const
126 {
127  return QList< QPair< QString, QColor > >();
128 }
129 
130 QList<QgsLayerTreeModelLegendNode *> QgsRasterRenderer::createLegendNodes( QgsLayerTreeLayer *nodeLayer )
131 {
132  QList<QgsLayerTreeModelLegendNode *> nodes;
133 
134  const QList< QPair< QString, QColor > > rasterItemList = legendSymbologyItems();
135  if ( rasterItemList.isEmpty() )
136  return nodes;
137 
138  // Paletted raster may have many colors, for example UInt16 may have 65536 colors
139  // and it is very slow, so we limit max count
140  int count = 0;
141  const int max_count = 1000;
142 
143  for ( auto itemIt = rasterItemList.constBegin(); itemIt != rasterItemList.constEnd(); ++itemIt, ++count )
144  {
145  nodes << new QgsRasterSymbolLegendNode( nodeLayer, itemIt->second, itemIt->first );
146 
147  if ( count == max_count )
148  {
149  const QString label = tr( "following %1 items\nnot displayed" ).arg( rasterItemList.size() - max_count );
150  nodes << new QgsSimpleLegendNode( nodeLayer, label );
151  break;
152  }
153  }
154 
155  return nodes;
156 }
157 
158 void QgsRasterRenderer::_writeXml( QDomDocument &doc, QDomElement &rasterRendererElem ) const
159 {
160  if ( rasterRendererElem.isNull() )
161  {
162  return;
163  }
164 
165  rasterRendererElem.setAttribute( QStringLiteral( "type" ), mType );
166  rasterRendererElem.setAttribute( QStringLiteral( "opacity" ), QString::number( mOpacity ) );
167  rasterRendererElem.setAttribute( QStringLiteral( "alphaBand" ), mAlphaBand );
168  rasterRendererElem.setAttribute( QStringLiteral( "nodataColor" ), mNodataColor.isValid() ? QgsColorUtils::colorToString( mNodataColor ) : QString() );
169 
170  if ( mRasterTransparency )
171  {
172  mRasterTransparency->writeXml( doc, rasterRendererElem );
173  }
174 
175  QDomElement minMaxOriginElem = doc.createElement( QStringLiteral( "minMaxOrigin" ) );
176  mMinMaxOrigin.writeXml( doc, minMaxOriginElem );
177  rasterRendererElem.appendChild( minMaxOriginElem );
178 }
179 
181 {
182  if ( !mNodataColor.isValid() )
183  return NODATA_COLOR;
184  else
185  return mNodataColor.rgba();
186 }
187 
188 void QgsRasterRenderer::readXml( const QDomElement &rendererElem )
189 {
190  if ( rendererElem.isNull() )
191  {
192  return;
193  }
194 
195  mType = rendererElem.attribute( QStringLiteral( "type" ) );
196  mOpacity = rendererElem.attribute( QStringLiteral( "opacity" ), QStringLiteral( "1.0" ) ).toDouble();
197  mAlphaBand = rendererElem.attribute( QStringLiteral( "alphaBand" ), QStringLiteral( "-1" ) ).toInt();
198  const QString colorEncoded = rendererElem.attribute( QStringLiteral( "nodataColor" ) );
199  mNodataColor = !colorEncoded.isEmpty() ? QgsColorUtils::colorFromString( colorEncoded ) : QColor();
200 
201  const QDomElement rasterTransparencyElem = rendererElem.firstChildElement( QStringLiteral( "rasterTransparency" ) );
202  if ( !rasterTransparencyElem.isNull() )
203  {
204  delete mRasterTransparency;
206  mRasterTransparency->readXml( rasterTransparencyElem );
207  }
208 
209  const QDomElement minMaxOriginElem = rendererElem.firstChildElement( QStringLiteral( "minMaxOrigin" ) );
210  if ( !minMaxOriginElem.isNull() )
211  {
212  mMinMaxOrigin.readXml( minMaxOriginElem );
213  }
214 }
215 
216 void QgsRasterRenderer::copyCommonProperties( const QgsRasterRenderer *other, bool copyMinMaxOrigin )
217 {
218  if ( !other )
219  return;
220 
221  setOpacity( other->opacity() );
222  setAlphaBand( other->alphaBand() );
223  setRasterTransparency( other->rasterTransparency() ? new QgsRasterTransparency( *other->rasterTransparency() ) : nullptr );
224  setNodataColor( other->nodataColor() );
225  if ( copyMinMaxOrigin )
226  setMinMaxOrigin( other->minMaxOrigin() );
227 }
228 
229 void QgsRasterRenderer::toSld( QDomDocument &doc, QDomElement &element, const QVariantMap & ) const
230 {
231  QDomElement rasterSymbolizerElem = doc.createElement( QStringLiteral( "sld:RasterSymbolizer" ) );
232  element.appendChild( rasterSymbolizerElem );
233 
234  // add opacity only is different from default
235  if ( !qgsDoubleNear( opacity(), 1.0 ) )
236  {
237  QDomElement opacityElem = doc.createElement( QStringLiteral( "sld:Opacity" ) );
238  opacityElem.appendChild( doc.createTextNode( QString::number( opacity() ) ) );
239  rasterSymbolizerElem.appendChild( opacityElem );
240  }
241 }
242 
244 {
245  return true;
246 }
QFlags< RasterRendererFlag > RasterRendererFlags
Flags which control behavior of raster renderers.
Definition: qgis.h:1161
DataType
Raster data types.
Definition: qgis.h:269
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ UnknownDataType
Unknown or unspecified type.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
Layer tree node points to a map layer.
static bool typeIsNumeric(Qgis::DataType type)
Returns true if data type is numeric.
Base class for processing filters like renderers, reprojector, resampler etc.
virtual Qgis::DataType dataType(int bandNo) const =0
Returns data type for the band specified by number.
virtual QgsRasterInterface * input() const
Current input.
virtual int bandCount() const =0
Gets number of bands.
QgsRasterInterface * mInput
void writeXml(QDomDocument &doc, QDomElement &parentElem) const
Serialize object.
void readXml(const QDomElement &elem)
Deserialize object.
Raster renderer pipe that applies colors to a raster.
QColor nodataColor() const
Returns the color to use for shading nodata pixels.
QgsRasterRenderer(QgsRasterInterface *input=nullptr, const QString &type=QString())
Constructor for QgsRasterRenderer.
const QgsRasterTransparency * rasterTransparency() const
virtual bool canCreateRasterAttributeTable() const
Returns true if the renderer is suitable for attribute table creation.
double mOpacity
Global alpha value (0-1)
bool setInput(QgsRasterInterface *input) override
Set input.
void setMinMaxOrigin(const QgsRasterMinMaxOrigin &origin)
Sets origin of min/max values.
~QgsRasterRenderer() override
virtual int inputBand() const
Returns the input band for the renderer, or -1 if no input band is available.
int mAlphaBand
Read alpha value from band.
virtual bool setInputBand(int band)
Attempts to set the input band for the renderer.
QRgb renderColorForNodataPixel() const
Returns the color for the renderer to use to represent nodata pixels.
virtual Qgis::RasterRendererFlags flags() const
Returns flags which dictate renderer behavior.
void _writeXml(QDomDocument &doc, QDomElement &rasterRendererElem) const
Write upper class info into rasterrenderer element (called by writeXml method of subclasses)
int bandCount() const override
Gets number of bands.
double opacity() const
Returns the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1....
void setAlphaBand(int band)
void setOpacity(double opacity)
Sets the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1....
QgsRasterMinMaxOrigin mMinMaxOrigin
Origin of min/max values.
QgsRasterTransparency * mRasterTransparency
Raster transparency per color or value. Overwrites global alpha value.
virtual QList< QgsLayerTreeModelLegendNode * > createLegendNodes(QgsLayerTreeLayer *nodeLayer)
Creates a set of legend nodes representing the renderer.
void setRasterTransparency(QgsRasterTransparency *t)
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
bool usesTransparency() const
void copyCommonProperties(const QgsRasterRenderer *other, bool copyMinMaxOrigin=true)
Copies common properties like opacity / transparency data from other renderer.
static const QRgb NODATA_COLOR
const QgsRasterMinMaxOrigin & minMaxOrigin() const
Returns const reference to origin of min/max values.
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 setNodataColor(const QColor &color)
Sets the color to use for shading nodata pixels.
virtual QList< QPair< QString, QColor > > legendSymbologyItems() const
Returns symbology items if provided by renderer.
void readXml(const QDomElement &rendererElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
Qgis::DataType dataType(int bandNo) const override
Returns data type for the band specified by number.
Implementation of legend node interface for displaying raster legend entries.
Defines the list of pixel values to be considered as transparent or semi transparent when rendering r...
void writeXml(QDomDocument &doc, QDomElement &parentElem) const
Writes the transparency information to an XML document.
bool isEmpty() const
True if there are no entries in the pixel lists except the nodata value.
void readXml(const QDomElement &elem)
Reads the transparency information from an XML document.
Implementation of legend node interface for displaying arbitrary label with icon.
An interface for classes which can visit style entity (e.g.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:5172
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39