QGIS API Documentation  2.14.0-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", QString::number( mClassificationMin ) );
228  rasterRendererElem.setAttribute( "classificationMax", QString::number( 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.
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
static int minMaxOriginFromName(const QString &theName)
virtual QgsRasterInterface * input() const
Current input.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &theList)
Set custom colormap.
double toDouble(bool *ok) const
bool isNoData(int row, int column)
Check if value at position is no data.
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.
bool usesTransparency() const
QgsRasterTransparency * mRasterTransparency
Raster transparency per color or value.
void writeXML(QDomDocument &doc, QDomElement &parent) const
bool setColor(int row, int column, QRgb color)
Set color on position.
static const QRgb NODATA_COLOR
int alphaValue(double, int theGlobalTransparency=255) const
Returns the transparency value for a single value Pixel.
QString number(int n, int base)
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.
double value(int row, int column) const
Read a single value if type of block is numeric.
void setAttribute(const QString &name, const QString &value)
int band() const
Returns the band used by the renderer.
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 shade(double, int *, int *, int *, int *)
generates and new RGBA value based on one input value
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:392
bool reset(QGis::DataType theDataType, int theWidth, int theHeight)
Reset block.
bool isNull() const
virtual void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) 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.
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)
void _writeXML(QDomDocument &doc, QDomElement &rasterRendererElem) const
Write upper class info into rasterrenderer element (called by writeXML method of subclasses) ...
QgsRasterInterface * mInput
void setRasterTransparency(QgsRasterTransparency *t)
Raster renderer pipe that applies colors to a raster.
bool isEmpty() const
Returns true if block is empty, i.e.