QGIS API Documentation  2.12.0-Lyon
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 
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 
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 
213 {
214  if ( mContrastEnhancement && mContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement )
215  {
216  QColor minColor = ( mGradient == BlackToWhite ) ? Qt::black : Qt::white;
217  QColor maxColor = ( mGradient == BlackToWhite ) ? Qt::white : Qt::black;
218  symbolItems.push_back( qMakePair( QString::number( mContrastEnhancement->minimumValue() ), minColor ) );
219  symbolItems.push_back( qMakePair( QString::number( mContrastEnhancement->maximumValue() ), maxColor ) );
220  }
221 }
222 
224 {
225  QList<int> bandList;
226  if ( mGrayBand != -1 )
227  {
228  bandList << mGrayBand;
229  }
230  return bandList;
231 }
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)
QDomNode appendChild(const QDomNode &newChild)
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
void writeXML(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
QList< int > usesBands() const override
Returns a list of band numbers used by the renderer.
QString attribute(const QString &name, const QString &defValue) 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:268
void readXML(const QDomElement &rendererElem) override
Sets base class members from xml.
QgsRasterBlock * block(int bandNo, QgsRectangle const &extent, int width, int height) override
Read block of data using given extent and size.
QgsRasterTransparency * mRasterTransparency
Raster transparency per color or value.
void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const override
Get symbology items if provided by renderer.
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)
QgsRasterInterface * clone() const override
Clone itself, create deep copy.
Raster data container.
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 toInt(bool *ok, int base) const
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:122
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:375
bool reset(QGis::DataType theDataType, int theWidth, int theHeight)
Reset block.
bool isNull() const
void setGradient(Gradient theGradient)
void setContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
int enhanceContrast(double)
Apply the contrast enhancement to a value.
double maximumValue() const
Return the maximum value for the contrast enhancement range.
QDomElement firstChildElement(const QString &tagName) const
virtual QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height)=0
Read block of data using given extent and size.
double mOpacity
Global alpha value (0-1)
Manipulates raster pixel values so that they enhanceContrast or clip into a specified numerical range...
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
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition: qgis.h:139
void setRasterTransparency(QgsRasterTransparency *t)
Raster renderer pipe that applies colors to a raster.
bool isEmpty() const
Returns true if block is empty, i.e.