QGIS API Documentation  2.14.11-Essen
qgssinglebandpseudocolorrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssinglebandpseudocolorrenderer.cpp
3  ------------------------------------
4  begin : January 2012
5  copyright : (C) 2012 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 
19 #include "qgsrastershader.h"
20 #include "qgsrastertransparency.h"
21 #include "qgsrasterviewport.h"
22 #include <QDomDocument>
23 #include <QDomElement>
24 #include <QImage>
25 
27  QgsRasterRenderer( input, "singlebandpseudocolor" )
28  , mShader( shader )
29  , mBand( band )
30  , mClassificationMin( std::numeric_limits<double>::quiet_NaN() )
31  , mClassificationMax( std::numeric_limits<double>::quiet_NaN() )
32  , mClassificationMinMaxOrigin( QgsRasterRenderer::MinMaxUnknown )
33 {
34 }
35 
37 {
38  delete mShader;
39 }
40 
42 {
43  if ( bandNo > mInput->bandCount() || bandNo <= 0 )
44  {
45  return;
46  }
47  mBand = bandNo;
48 }
49 
51 {
52  QgsRasterShader *shader = nullptr;
53 
54  if ( mShader )
55  {
56  shader = new QgsRasterShader( mShader->minimumValue(), mShader->maximumValue() );
57 
58  // Shader function
59  const QgsColorRampShader* origColorRampShader = dynamic_cast<const QgsColorRampShader*>( mShader->rasterShaderFunction() );
60 
61  if ( origColorRampShader )
62  {
63  QgsColorRampShader * colorRampShader = new QgsColorRampShader( mShader->minimumValue(), mShader->maximumValue() );
64 
65  colorRampShader->setColorRampType( origColorRampShader->colorRampType() );
66 
67  colorRampShader->setColorRampItemList( origColorRampShader->colorRampItemList() );
68  shader->setRasterShaderFunction( colorRampShader );
69  }
70  }
71  QgsSingleBandPseudoColorRenderer * renderer = new QgsSingleBandPseudoColorRenderer( nullptr, mBand, shader );
72 
73  renderer->setOpacity( mOpacity );
74  renderer->setAlphaBand( mAlphaBand );
76 
77  return renderer;
78 }
79 
81 {
82  delete mShader;
83  mShader = shader;
84 }
85 
87 {
88  if ( elem.isNull() )
89  {
90  return nullptr;
91  }
92 
93  int band = elem.attribute( "band", "-1" ).toInt();
94  QgsRasterShader* shader = nullptr;
95  QDomElement rasterShaderElem = elem.firstChildElement( "rastershader" );
96  if ( !rasterShaderElem.isNull() )
97  {
98  shader = new QgsRasterShader();
99  shader->readXML( rasterShaderElem );
100  }
101 
103  r->readXML( elem );
104 
105  // TODO: add _readXML in superclass?
106  r->setClassificationMin( elem.attribute( "classificationMin", "NaN" ).toDouble() );
107  r->setClassificationMax( elem.attribute( "classificationMax", "NaN" ).toDouble() );
108  r->setClassificationMinMaxOrigin( QgsRasterRenderer::minMaxOriginFromName( elem.attribute( "classificationMinMaxOrigin", "Unknown" ) ) );
109 
110  return r;
111 }
112 
113 QgsRasterBlock* QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
114 {
115  Q_UNUSED( bandNo );
116 
117  QgsRasterBlock *outputBlock = new QgsRasterBlock();
118  if ( !mInput || !mShader )
119  {
120  return outputBlock;
121  }
122 
123 
124  QgsRasterBlock *inputBlock = mInput->block( mBand, extent, width, height );
125  if ( !inputBlock || inputBlock->isEmpty() )
126  {
127  QgsDebugMsg( "No raster data!" );
128  delete inputBlock;
129  return outputBlock;
130  }
131 
132  //rendering is faster without considering user-defined transparency
133  bool hasTransparency = usesTransparency();
134 
135  QgsRasterBlock *alphaBlock = nullptr;
136  if ( mAlphaBand > 0 && mAlphaBand != mBand )
137  {
138  alphaBlock = mInput->block( mAlphaBand, extent, width, height );
139  if ( !alphaBlock || alphaBlock->isEmpty() )
140  {
141  delete inputBlock;
142  delete alphaBlock;
143  return outputBlock;
144  }
145  }
146  else if ( mAlphaBand == mBand )
147  {
148  alphaBlock = inputBlock;
149  }
150 
151  if ( !outputBlock->reset( QGis::ARGB32_Premultiplied, width, height ) )
152  {
153  delete inputBlock;
154  delete alphaBlock;
155  return outputBlock;
156  }
157 
158  QRgb myDefaultColor = NODATA_COLOR;
159 
160  for ( qgssize i = 0; i < ( qgssize )width*height; i++ )
161  {
162  if ( inputBlock->isNoData( i ) )
163  {
164  outputBlock->setColor( i, myDefaultColor );
165  continue;
166  }
167  double val = inputBlock->value( i );
168  int red, green, blue, alpha;
169  if ( !mShader->shade( val, &red, &green, &blue, &alpha ) )
170  {
171  outputBlock->setColor( i, myDefaultColor );
172  continue;
173  }
174 
175  if ( alpha < 255 )
176  {
177  // Working with premultiplied colors, so multiply values by alpha
178  red *= ( alpha / 255.0 );
179  blue *= ( alpha / 255.0 );
180  green *= ( alpha / 255.0 );
181  }
182 
183  if ( !hasTransparency )
184  {
185  outputBlock->setColor( i, qRgba( red, green, blue, alpha ) );
186  }
187  else
188  {
189  //opacity
190  double currentOpacity = mOpacity;
191  if ( mRasterTransparency )
192  {
193  currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0;
194  }
195  if ( mAlphaBand > 0 )
196  {
197  currentOpacity *= alphaBlock->value( i ) / 255.0;
198  }
199 
200  outputBlock->setColor( i, qRgba( currentOpacity * red, currentOpacity * green, currentOpacity * blue, currentOpacity * alpha ) );
201  }
202  }
203 
204  delete inputBlock;
205  if ( mAlphaBand > 0 && mBand != mAlphaBand )
206  {
207  delete alphaBlock;
208  }
209 
210  return outputBlock;
211 }
212 
214 {
215  if ( parentElem.isNull() )
216  {
217  return;
218  }
219 
220  QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" );
221  _writeXML( doc, rasterRendererElem );
222  rasterRendererElem.setAttribute( "band", mBand );
223  if ( mShader )
224  {
225  mShader->writeXML( doc, rasterRendererElem ); //todo: include color ramp items directly in this renderer
226  }
227  rasterRendererElem.setAttribute( "classificationMin", QgsRasterBlock::printValue( mClassificationMin ) );
228  rasterRendererElem.setAttribute( "classificationMax", QgsRasterBlock::printValue( mClassificationMax ) );
229  rasterRendererElem.setAttribute( "classificationMinMaxOrigin", QgsRasterRenderer::minMaxOriginName( mClassificationMinMaxOrigin ) );
230 
231  parentElem.appendChild( rasterRendererElem );
232 }
233 
235 {
236  if ( mShader )
237  {
238  QgsRasterShaderFunction* shaderFunction = mShader->rasterShaderFunction();
239  if ( shaderFunction )
240  {
241  shaderFunction->legendSymbologyItems( symbolItems );
242  }
243  }
244 }
245 
247 {
248  QList<int> bandList;
249  if ( mBand != -1 )
250  {
251  bandList << mBand;
252  }
253  return bandList;
254 }
virtual int bandCount() const =0
Get number of bands.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Interface for all raster shaders.
static QString printValue(double value)
Print double value with all necessary significant digits.
void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const override
Get symbology items if provided by renderer.
QDomNode appendChild(const QDomNode &newChild)
QgsSingleBandPseudoColorRenderer * clone() const override
Clone itself, create deep copy.
static QgsRasterRenderer * create(const QDomElement &elem, QgsRasterInterface *input)
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
QString attribute(const QString &name, const QString &defValue) const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
int alphaValue(double, int theGlobalTransparency=255) const
Returns the transparency value for a single value Pixel.
virtual QgsRasterInterface * input() const
Current input.
static int minMaxOriginFromName(const QString &theName)
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &theList)
Set custom colormap.
double toDouble(bool *ok) const
virtual void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const
bool isNoData(int row, int column)
Check if value at position is no data.
void writeXML(QDomDocument &doc, QDomElement &parent) const
void setShader(QgsRasterShader *shader)
Takes ownership of the shader.
void readXML(const QDomElement &rendererElem) override
Sets base class members from xml.
void writeXML(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
QgsRasterTransparency * mRasterTransparency
Raster transparency per color or value.
bool setColor(int row, int column, QRgb color)
Set color on position.
static const QRgb NODATA_COLOR
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition: qgis.h:146
Raster data container.
QgsSingleBandPseudoColorRenderer(QgsRasterInterface *input, int band, QgsRasterShader *shader)
Note: takes ownership of QgsRasterShader.
void setAttribute(const QString &name, const QString &value)
int toInt(bool *ok, int base) const
QgsRasterShaderFunction * rasterShaderFunction()
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height) override
Read block of data using given extent and size.
The raster shade function applies a shader to a pixel at render time - typically used to render grays...
double maximumValue()
Return the maximum value for the raster shader.
Raster renderer pipe for single band pseudocolor.
bool usesTransparency() const
bool shade(double, int *, int *, int *, int *)
generates and new RGBA value based on one input value
bool isEmpty() const
Returns true if block is empty, i.e.
void _writeXML(QDomDocument &doc, QDomElement &rasterRendererElem) const
Write upper class info into rasterrenderer element (called by writeXML method of subclasses) ...
int mAlphaBand
Read alpha value from band.
void setAlphaBand(int band)
QList< int > usesBands() const override
Returns a list of band numbers used by the renderer.
void setRasterShaderFunction(QgsRasterShaderFunction *)
A public method that allows the user to set their own shader function.
Base class for processing filters like renderers, reprojector, resampler etc.
void setColorRampType(QgsColorRampShader::ColorRamp_TYPE theColorRampType)
Set the color ramp type.
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...
Definition: qgis.h:400
bool reset(QGis::DataType theDataType, int theWidth, int theHeight)
Reset block.
bool isNull() const
virtual QgsRectangle extent()
Get the extent of the interface.
QDomElement firstChildElement(const QString &tagName) const
static QString minMaxOriginName(int theOrigin)
virtual QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height)=0
Read block of data using given extent and size.
double minimumValue()
Return the minimum value for the raster shader.
double value(int row, int column) const
Read a single value if type of block is numeric.
void setBand(int bandNo)
Sets the band used by the renderer.
double mOpacity
Global alpha value (0-1)
void readXML(const QDomElement &elem)
Defines the list of pixel values to be considered as transparent or semi transparent when rendering r...
void setOpacity(double opacity)
QDomElement createElement(const QString &tagName)
QgsRasterInterface * mInput
void setRasterTransparency(QgsRasterTransparency *t)
Raster renderer pipe that applies colors to a raster.
int band() const
Returns the band used by the renderer.