QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgssinglebandgrayrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssinglebandgrayrenderer.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 
19 #include "qgscontrastenhancement.h"
20 #include "qgsrastertransparency.h"
21 #include <QDomDocument>
22 #include <QDomElement>
23 #include <QImage>
24 
26  QgsRasterRenderer( input, "singlebandgray" ), mGrayBand( grayBand ), mGradient( BlackToWhite ), mContrastEnhancement( 0 )
27 {
28 }
29 
31 {
32  delete mContrastEnhancement;
33 }
34 
36 {
37  QgsSingleBandGrayRenderer * renderer = new QgsSingleBandGrayRenderer( 0, mGrayBand );
38  renderer->setOpacity( mOpacity );
39  renderer->setAlphaBand( mAlphaBand );
41  renderer->setGradient( mGradient );
42  if ( mContrastEnhancement )
43  {
44  renderer->setContrastEnhancement( new QgsContrastEnhancement( *mContrastEnhancement ) );
45  }
46  return renderer;
47 }
48 
50 {
51  if ( elem.isNull() )
52  {
53  return 0;
54  }
55 
56  int grayBand = elem.attribute( "grayBand", "-1" ).toInt();
57  QgsSingleBandGrayRenderer* r = new QgsSingleBandGrayRenderer( input, grayBand );
58  r->readXML( elem );
59 
60  if ( elem.attribute( "gradient" ) == "WhiteToBlack" )
61  {
62  r->setGradient( WhiteToBlack ); // BlackToWhite is default
63  }
64 
65  QDomElement contrastEnhancementElem = elem.firstChildElement( "contrastEnhancement" );
66  if ( !contrastEnhancementElem.isNull() )
67  {
69  input->dataType( grayBand ) ) );
70  ce->readXML( contrastEnhancementElem );
71  r->setContrastEnhancement( ce );
72  }
73  return r;
74 }
75 
77 {
78  delete mContrastEnhancement;
79  mContrastEnhancement = ce;
80 }
81 
82 QgsRasterBlock* QgsSingleBandGrayRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
83 {
84  Q_UNUSED( bandNo );
85  QgsDebugMsg( QString( "width = %1 height = %2" ).arg( width ).arg( height ) );
86 
87  QgsRasterBlock *outputBlock = new QgsRasterBlock();
88  if ( !mInput )
89  {
90  return outputBlock;
91  }
92 
93  QgsRasterBlock *inputBlock = mInput->block( mGrayBand, extent, width, height );
94  if ( !inputBlock || inputBlock->isEmpty() )
95  {
96  QgsDebugMsg( "No raster data!" );
97  delete inputBlock;
98  return outputBlock;
99  }
100 
101  QgsRasterBlock *alphaBlock = 0;
102 
103  if ( mAlphaBand > 0 && mGrayBand != mAlphaBand )
104  {
105  alphaBlock = mInput->block( mAlphaBand, extent, width, height );
106  if ( !alphaBlock || alphaBlock->isEmpty() )
107  {
108  // TODO: better to render without alpha
109  delete inputBlock;
110  delete alphaBlock;
111  return outputBlock;
112  }
113  }
114  else if ( mAlphaBand > 0 )
115  {
116  alphaBlock = inputBlock;
117  }
118 
119  if ( !outputBlock->reset( QGis::ARGB32_Premultiplied, width, height ) )
120  {
121  delete inputBlock;
122  delete alphaBlock;
123  return outputBlock;
124  }
125 
126  QRgb myDefaultColor = NODATA_COLOR;
127  for ( qgssize i = 0; i < ( qgssize )width*height; i++ )
128  {
129  if ( inputBlock->isNoData( i ) )
130  {
131  outputBlock->setColor( i, myDefaultColor );
132  continue;
133  }
134  double grayVal = inputBlock->value( i );
135 
136  double currentAlpha = mOpacity;
137  if ( mRasterTransparency )
138  {
139  currentAlpha = mRasterTransparency->alphaValue( grayVal, mOpacity * 255 ) / 255.0;
140  }
141  if ( mAlphaBand > 0 )
142  {
143  currentAlpha *= alphaBlock->value( i ) / 255.0;
144  }
145 
146  if ( mContrastEnhancement )
147  {
148  if ( !mContrastEnhancement->isValueInDisplayableRange( grayVal ) )
149  {
150  outputBlock->setColor( i, myDefaultColor );
151  continue;
152  }
153  grayVal = mContrastEnhancement->enhanceContrast( grayVal );
154  }
155 
156  if ( mGradient == WhiteToBlack )
157  {
158  grayVal = 255 - grayVal;
159  }
160 
161  if ( qgsDoubleNear( currentAlpha, 1.0 ) )
162  {
163  outputBlock->setColor( i, qRgba( grayVal, grayVal, grayVal, 255 ) );
164  }
165  else
166  {
167  outputBlock->setColor( i, qRgba( currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * 255 ) );
168  }
169  }
170 
171  delete inputBlock;
172  if ( mAlphaBand > 0 && mGrayBand != mAlphaBand )
173  {
174  delete alphaBlock;
175  }
176 
177  return outputBlock;
178 }
179 
180 void QgsSingleBandGrayRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
181 {
182  if ( parentElem.isNull() )
183  {
184  return;
185  }
186 
187  QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" );
188  _writeXML( doc, rasterRendererElem );
189 
190  rasterRendererElem.setAttribute( "grayBand", mGrayBand );
191 
192  QString gradient;
193  if ( mGradient == BlackToWhite )
194  {
195  gradient = "BlackToWhite";
196  }
197  else
198  {
199  gradient = "WhiteToBlack";
200  }
201  rasterRendererElem.setAttribute( "gradient", gradient );
202 
203  if ( mContrastEnhancement )
204  {
205  QDomElement contrastElem = doc.createElement( "contrastEnhancement" );
206  mContrastEnhancement->writeXML( doc, contrastElem );
207  rasterRendererElem.appendChild( contrastElem );
208  }
209  parentElem.appendChild( rasterRendererElem );
210 }
211 
212 void QgsSingleBandGrayRenderer::legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const
213 {
214  if ( mContrastEnhancement && mContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement )
215  {
216  symbolItems.push_back( qMakePair( QString::number( mContrastEnhancement->minimumValue() ), QColor( 0, 0, 0 ) ) );
217  symbolItems.push_back( qMakePair( QString::number( mContrastEnhancement->maximumValue() ), QColor( 255, 255, 255 ) ) );
218  }
219 }
220 
222 {
223  QList<int> bandList;
224  if ( mGrayBand != -1 )
225  {
226  bandList << mGrayBand;
227  }
228  return bandList;
229 }
void writeXML(QDomDocument &doc, QDomElement &parentElem) const
A rectangle specified with double values.
Definition: qgsrectangle.h:35
static QgsRasterRenderer * create(const QDomElement &elem, QgsRasterInterface *input)
QgsSingleBandGrayRenderer(QgsRasterInterface *input, int grayBand)
void readXML(const QDomElement &elem)
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
bool isValueInDisplayableRange(double)
Return true if pixel is in stretable range, false if pixel is outside of range (i.e., clipped)
bool isNoData(int row, int column)
Check if value at position is no data.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:325
QList< int > usesBands() const
Returns a list of band numbers used by the renderer.
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
int alphaValue(double, int theGlobalTransparency=255) const
Returns the transparency value for a single value Pixel.
Raster data container.
double value(int row, int column) const
Read a single value if type of block is numeric.
QgsRasterBlock * block(int bandNo, QgsRectangle const &extent, int width, int height)
Read block of data using given extent and size.
Raster renderer pipe for single band gray.
double minimumValue() const
Return the minimum value for the contrast enhancement range.
DataType
Raster data types.
Definition: qgis.h:204
int mAlphaBand
Read alpha value from band.
virtual QGis::DataType dataType(int bandNo) const =0
Returns data type for the band specified by number.
void setAlphaBand(int band)
Base class for processing filters like renderers, reprojector, resampler etc.
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.
void setGradient(Gradient theGradient)
void setContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
int enhanceContrast(double)
Apply the contrast enhancement to a value.
QgsRasterInterface * clone() const
Clone itself, create deep copy.
double maximumValue() const
Return the maximum value for the contrast enhancement range.
virtual QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height)=0
Read block of data using given extent and size.
void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const
Get symbology items if provided by renderer.
double mOpacity
Global alpha value (0-1)
Manipulates raster pixel values so that they enhanceContrast or clip into a specified numerical range...
void writeXML(QDomDocument &doc, QDomElement &parentElem) const
Write base class members to xml.
Defines the list of pixel values to be considered as transparent or semi transparent when rendering r...
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.