QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgspalettedrasterrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspalettedrasterrenderer.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 "qgsrastertransparency.h"
20 #include "qgsrasterviewport.h"
21 #include <QColor>
22 #include <QDomDocument>
23 #include <QDomElement>
24 #include <QImage>
25 #include <QVector>
26 
28  QColor* colorArray, int nColors, const QVector<QString> labels ):
29  QgsRasterRenderer( input, "paletted" ), mBand( bandNumber ), mNColors( nColors ), mLabels( labels )
30 {
31  mColors = new QRgb[nColors];
32  for ( int i = 0; i < nColors; ++i )
33  {
34  mColors[i] = colorArray[i].rgba();
35  }
36  delete[] colorArray;
37 }
38 
39 QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterInterface* input, int bandNumber, QRgb* colorArray, int nColors, const QVector<QString> labels ):
40  QgsRasterRenderer( input, "paletted" ), mBand( bandNumber ), mColors( colorArray ), mNColors( nColors ), mLabels( labels )
41 {
42 }
43 
45 {
46  delete[] mColors;
47 }
48 
50 {
51  QgsPalettedRasterRenderer * renderer = new QgsPalettedRasterRenderer( 0, mBand, rgbArray(), mNColors );
52  renderer->setOpacity( mOpacity );
53  renderer->setAlphaBand( mAlphaBand );
55  renderer->mLabels = mLabels;
56  return renderer;
57 }
58 
60 {
61  if ( elem.isNull() )
62  {
63  return 0;
64  }
65 
66  int bandNumber = elem.attribute( "band", "-1" ).toInt();
67  int nColors = 0;
68  QRgb* colors = 0;
69  QVector<QString> labels;
70 
71  QDomElement paletteElem = elem.firstChildElement( "colorPalette" );
72  if ( !paletteElem.isNull() )
73  {
74  QDomNodeList paletteEntries = paletteElem.elementsByTagName( "paletteEntry" );
75 
76  QDomElement entryElem;
77  int value;
78  nColors = 0;
79 
80  // We cannot believe that data are correct, check first max value
81  for ( int i = 0; i < paletteEntries.size(); ++i )
82  {
83  entryElem = paletteEntries.at( i ).toElement();
84  // Could be written as doubles (with .0000) in old project files
85  value = ( int )entryElem.attribute( "value", "0" ).toDouble();
86  if ( value >= nColors && value <= 10000 ) nColors = value + 1;
87  }
88  QgsDebugMsg( QString( "nColors = %1" ).arg( nColors ) );
89 
90  colors = new QRgb[ nColors ];
91 
92  for ( int i = 0; i < nColors; ++i )
93  {
94  entryElem = paletteEntries.at( i ).toElement();
95  value = ( int )entryElem.attribute( "value", "0" ).toDouble();
96  QgsDebugMsg( entryElem.attribute( "color", "#000000" ) );
97  if ( value >= 0 && value < nColors )
98  {
99  colors[value] = QColor( entryElem.attribute( "color", "#000000" ) ).rgba();
100  QString label = entryElem.attribute( "label" );
101  if ( !label.isEmpty() )
102  {
103  if ( value >= labels.size() ) labels.resize( value + 1 );
104  labels[value] = label;
105  }
106  }
107  else
108  {
109  QgsDebugMsg( QString( "value %1 out of range" ).arg( value ) );
110  }
111  }
112  }
113  QgsPalettedRasterRenderer* r = new QgsPalettedRasterRenderer( input, bandNumber, colors, nColors, labels );
114  r->readXML( elem );
115  return r;
116 }
117 
119 {
120  if ( mNColors < 1 )
121  {
122  return 0;
123  }
124  QColor* colorArray = new QColor[ mNColors ];
125  for ( int i = 0; i < mNColors; ++i )
126  {
127  colorArray[i] = QColor( mColors[i] );
128  }
129  return colorArray;
130 }
131 
133 {
134  if ( mNColors < 1 )
135  {
136  return 0;
137  }
138  QRgb* rgbValues = new QRgb[mNColors];
139  for ( int i = 0; i < mNColors; ++i )
140  {
141  rgbValues[i] = mColors[i];
142  }
143  return rgbValues;
144 }
145 
146 void QgsPalettedRasterRenderer::setLabel( int idx, QString label )
147 {
148  if ( idx >= mLabels.size() )
149  {
150  mLabels.resize( idx + 1 );
151  }
152  mLabels[idx] = label;
153 }
154 
155 QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
156 {
157  QgsRasterBlock *outputBlock = new QgsRasterBlock();
158  if ( !mInput || mNColors == 0 )
159  {
160  return outputBlock;
161  }
162 
163  QgsRasterBlock *inputBlock = mInput->block( bandNo, extent, width, height );
164 
165  if ( !inputBlock || inputBlock->isEmpty() )
166  {
167  QgsDebugMsg( "No raster data!" );
168  delete inputBlock;
169  return outputBlock;
170  }
171 
172  double currentOpacity = mOpacity;
173 
174  //rendering is faster without considering user-defined transparency
175  bool hasTransparency = usesTransparency();
176  QgsRasterBlock *alphaBlock = 0;
177 
178  if ( mAlphaBand > 0 && mAlphaBand != mBand )
179  {
180  alphaBlock = mInput->block( mAlphaBand, extent, width, height );
181  if ( !alphaBlock || alphaBlock->isEmpty() )
182  {
183  delete inputBlock;
184  delete alphaBlock;
185  return outputBlock;
186  }
187  }
188  else if ( mAlphaBand == mBand )
189  {
190  alphaBlock = inputBlock;
191  }
192 
193  if ( !outputBlock->reset( QGis::ARGB32_Premultiplied, width, height ) )
194  {
195  delete inputBlock;
196  delete alphaBlock;
197  return outputBlock;
198  }
199 
200  QRgb myDefaultColor = NODATA_COLOR;
201 
202  //use direct data access instead of QgsRasterBlock::setValue
203  //because of performance
204  unsigned int* outputData = ( unsigned int* )( outputBlock->bits() );
205 
206  qgssize rasterSize = ( qgssize )width * height;
207  for ( qgssize i = 0; i < rasterSize; ++i )
208  {
209  if ( inputBlock->isNoData( i ) )
210  {
211  outputData[i] = myDefaultColor;
212  continue;
213  }
214  int val = ( int ) inputBlock->value( i );
215  if ( !hasTransparency )
216  {
217  outputData[i] = mColors[val];
218  }
219  else
220  {
221  currentOpacity = mOpacity;
222  if ( mRasterTransparency )
223  {
224  currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0;
225  }
226  if ( mAlphaBand > 0 )
227  {
228  currentOpacity *= alphaBlock->value( i ) / 255.0;
229  }
230  QColor currentColor = QColor( mColors[val] );
231  outputData[i] = qRgba( currentOpacity * currentColor.red(), currentOpacity * currentColor.green(), currentOpacity * currentColor.blue(), currentOpacity * 255 );
232  }
233  }
234 
235  delete inputBlock;
236  if ( mAlphaBand > 0 && mBand != mAlphaBand )
237  {
238  delete alphaBlock;
239  }
240 
241  return outputBlock;
242 }
243 
244 void QgsPalettedRasterRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
245 {
246  if ( parentElem.isNull() )
247  {
248  return;
249  }
250 
251  QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" );
252  _writeXML( doc, rasterRendererElem );
253 
254  rasterRendererElem.setAttribute( "band", mBand );
255  QDomElement colorPaletteElem = doc.createElement( "colorPalette" );
256  for ( int i = 0; i < mNColors; ++i )
257  {
258  QDomElement colorElem = doc.createElement( "paletteEntry" );
259  colorElem.setAttribute( "value", i );
260  colorElem.setAttribute( "color", QColor( mColors[i] ).name() );
261  if ( !label( i ).isEmpty() )
262  {
263  colorElem.setAttribute( "label", label( i ) );
264  }
265  colorPaletteElem.appendChild( colorElem );
266  }
267  rasterRendererElem.appendChild( colorPaletteElem );
268 
269  parentElem.appendChild( rasterRendererElem );
270 }
271 
272 void QgsPalettedRasterRenderer::legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const
273 {
274  for ( int i = 0; i < mNColors; ++i )
275  {
276  QString lab = label( i ).isEmpty() ? QString::number( i ) : label( i );
277  symbolItems.push_back( qMakePair( lab, QColor( mColors[i] ) ) );
278  }
279 }
280 
282 {
283  QList<int> bandList;
284  if ( mBand != -1 )
285  {
286  bandList << mBand;
287  }
288  return bandList;
289 }
A rectangle specified with double values.
Definition: qgsrectangle.h:35
void writeXML(QDomDocument &doc, QDomElement &parentElem) const
Write base class members to xml.
QString label(int idx) const
Return optional category label.
Renderer for paletted raster images.
QList< int > usesBands() const
Returns a list of band numbers used by the renderer.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
bool isNoData(int row, int column)
Check if value at position is no data.
QgsPalettedRasterRenderer(QgsRasterInterface *input, int bandNumber, QColor *colorArray, int nColors, const QVector< QString > labels=QVector< QString >())
Renderer owns color array.
QgsRasterInterface * clone() const
Clone itself, create deep copy.
bool usesTransparency() const
QgsRasterTransparency * mRasterTransparency
Raster transparency per color or value.
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, const QgsRectangle &extent, int width, int height)
Read block of data using given extent and size.
int nColors() const
Returns number of colors.
void setLabel(int idx, QString label)
Set category label.
int mAlphaBand
Read alpha value from band.
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:420
void readXML(const QDomElement &rendererElem)
Sets base class members from xml.
static QgsRasterRenderer * create(const QDomElement &elem, QgsRasterInterface *input)
bool reset(QGis::DataType theDataType, int theWidth, int theHeight)
Reset block.
void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const
Get symbology items if provided by renderer.
char * bits(int row, int column)
Get pointer to data.
QRgb * rgbArray() const
Returns copy of rgb array (caller takes ownership)
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)
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.
QColor * colors() const
Returns copy of color array (caller takes ownership)
bool isEmpty() const
Returns true if block is empty, i.e.