QGIS API Documentation  2.4.0-Chugiak
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 {
44 
45  if ( mShader )
46  {
48 
49  // Shader function
50  const QgsColorRampShader* origColorRampShader = dynamic_cast<const QgsColorRampShader*>( mShader->rasterShaderFunction() );
51 
52  if ( origColorRampShader )
53  {
55 
56  colorRampShader->setColorRampType( origColorRampShader->colorRampType() );
57 
58  colorRampShader->setColorRampItemList( origColorRampShader->colorRampItemList() );
59  shader->setRasterShaderFunction( colorRampShader );
60  }
61  }
63 
64  renderer->setOpacity( mOpacity );
65  renderer->setAlphaBand( mAlphaBand );
67 
68  return renderer;
69 }
70 
72 {
73  delete mShader;
74  mShader = shader;
75 }
76 
78 {
79  if ( elem.isNull() )
80  {
81  return 0;
82  }
83 
84  int band = elem.attribute( "band", "-1" ).toInt();
86  QDomElement rasterShaderElem = elem.firstChildElement( "rastershader" );
87  if ( !rasterShaderElem.isNull() )
88  {
89  shader = new QgsRasterShader();
90  shader->readXML( rasterShaderElem );
91  }
92 
94  r->readXML( elem );
95 
96  // TODO: add _readXML in superclass?
97  r->setClassificationMin( elem.attribute( "classificationMin", "NaN" ).toDouble() );
98  r->setClassificationMax( elem.attribute( "classificationMax", "NaN" ).toDouble() );
99  r->setClassificationMinMaxOrigin( QgsRasterRenderer::minMaxOriginFromName( elem.attribute( "classificationMinMaxOrigin", "Unknown" ) ) );
100 
101  return r;
102 }
103 
104 QgsRasterBlock* QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
105 {
106  Q_UNUSED( bandNo );
107 
108  QgsRasterBlock *outputBlock = new QgsRasterBlock();
109  if ( !mInput || !mShader )
110  {
111  return outputBlock;
112  }
113 
114 
115  QgsRasterBlock *inputBlock = mInput->block( mBand, extent, width, height );
116  if ( !inputBlock || inputBlock->isEmpty() )
117  {
118  QgsDebugMsg( "No raster data!" );
119  delete inputBlock;
120  return outputBlock;
121  }
122 
123  //rendering is faster without considering user-defined transparency
124  bool hasTransparency = usesTransparency();
125 
126  QgsRasterBlock *alphaBlock = 0;
127  if ( mAlphaBand > 0 && mAlphaBand != mBand )
128  {
129  alphaBlock = mInput->block( mAlphaBand, extent, width, height );
130  if ( !alphaBlock || alphaBlock->isEmpty() )
131  {
132  delete inputBlock;
133  delete alphaBlock;
134  return outputBlock;
135  }
136  }
137  else if ( mAlphaBand == mBand )
138  {
139  alphaBlock = inputBlock;
140  }
141 
142  if ( !outputBlock->reset( QGis::ARGB32_Premultiplied, width, height ) )
143  {
144  delete inputBlock;
145  delete alphaBlock;
146  return outputBlock;
147  }
148 
149  QRgb myDefaultColor = NODATA_COLOR;
150 
151  for ( qgssize i = 0; i < ( qgssize )width*height; i++ )
152  {
153  if ( inputBlock->isNoData( i ) )
154  {
155  outputBlock->setColor( i, myDefaultColor );
156  continue;
157  }
158  double val = inputBlock->value( i );
159  int red, green, blue, alpha;
160  if ( !mShader->shade( val, &red, &green, &blue, &alpha ) )
161  {
162  outputBlock->setColor( i, myDefaultColor );
163  continue;
164  }
165 
166  if ( alpha < 255 )
167  {
168  // Working with premultiplied colors, so multiply values by alpha
169  red *= ( alpha / 255.0 );
170  blue *= ( alpha / 255.0 );
171  green *= ( alpha / 255.0 );
172  }
173 
174  if ( !hasTransparency )
175  {
176  outputBlock->setColor( i, qRgba( red, green, blue, alpha ) );
177  }
178  else
179  {
180  //opacity
181  double currentOpacity = mOpacity;
182  if ( mRasterTransparency )
183  {
184  currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0;
185  }
186  if ( mAlphaBand > 0 )
187  {
188  currentOpacity *= alphaBlock->value( i ) / 255.0;
189  }
190 
191  outputBlock->setColor( i, qRgba( currentOpacity * red, currentOpacity * green, currentOpacity * blue, currentOpacity * alpha ) );
192  }
193  }
194 
195  delete inputBlock;
196  if ( mAlphaBand > 0 && mBand != mAlphaBand )
197  {
198  delete alphaBlock;
199  }
200 
201  return outputBlock;
202 }
203 
204 void QgsSingleBandPseudoColorRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
205 {
206  if ( parentElem.isNull() )
207  {
208  return;
209  }
210 
211  QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" );
212  _writeXML( doc, rasterRendererElem );
213  rasterRendererElem.setAttribute( "band", mBand );
214  if ( mShader )
215  {
216  mShader->writeXML( doc, rasterRendererElem ); //todo: include color ramp items directly in this renderer
217  }
218  rasterRendererElem.setAttribute( "classificationMin", QString::number( mClassificationMin ) );
219  rasterRendererElem.setAttribute( "classificationMax", QString::number( mClassificationMax ) );
220  rasterRendererElem.setAttribute( "classificationMinMaxOrigin", QgsRasterRenderer::minMaxOriginName( mClassificationMinMaxOrigin ) );
221 
222  parentElem.appendChild( rasterRendererElem );
223 }
224 
225 void QgsSingleBandPseudoColorRenderer::legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const
226 {
227  if ( mShader )
228  {
230  if ( shaderFunction )
231  {
232  shaderFunction->legendSymbologyItems( symbolItems );
233  }
234  }
235 }
236 
238 {
239  QList<int> bandList;
240  if ( mBand != -1 )
241  {
242  bandList << mBand;
243  }
244  return bandList;
245 }
void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const
Get symbology items if provided by renderer.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Interface for all raster shaders.
static int minMaxOriginFromName(QString theName)
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.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
QList< int > usesBands() const
Returns a list of band numbers used by the renderer.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &theList)
Set custom colormap.
bool isNoData(int row, int column)
Check if value at position is no data.
void setShader(QgsRasterShader *shader)
Takes ownership of the shader.
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.
Raster data container.
QgsSingleBandPseudoColorRenderer(QgsRasterInterface *input, int band, QgsRasterShader *shader)
Note: takes ownership of QgsRasterShader.
QgsRasterInterface * clone() const
Clone itself, create deep copy.
double value(int row, int column) const
Read a single value if type of block is numeric.
QgsRasterShaderFunction * rasterShaderFunction()
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
void writeXML(QDomDocument &doc, QDomElement &parentElem) const
Write base class members to xml.
int mAlphaBand
Read alpha value from band.
void setAlphaBand(int band)
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:424
void readXML(const QDomElement &rendererElem)
Sets base class members from xml.
bool reset(QGis::DataType theDataType, int theWidth, int theHeight)
Reset block.
virtual void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height)
Read block of data using given extent and size.
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 mOpacity
Global alpha value (0-1)
void readXML(const QDomElement &elem)
void setOpacity(double opacity)
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.