QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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 
27  QColor* colorArray, int nColors ):
28  QgsRasterRenderer( input, "paletted" ), mBand( bandNumber ), mNColors( nColors )
29 {
30  mColors = new QRgb[nColors];
31  for ( int i = 0; i < nColors; ++i )
32  {
33  mColors[i] = colorArray[i].rgba();
34  }
35  delete[] colorArray;
36 }
37 
38 QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterInterface* input, int bandNumber, QRgb* colorArray, int nColors ):
39  QgsRasterRenderer( input, "paletted" ), mBand( bandNumber ), mColors( colorArray ), mNColors( nColors )
40 {
41 }
42 
44 {
45  delete[] mColors;
46 }
47 
49 {
51  renderer->setOpacity( mOpacity );
52  renderer->setAlphaBand( mAlphaBand );
54  return renderer;
55 }
56 
58 {
59  if ( elem.isNull() )
60  {
61  return 0;
62  }
63 
64  int bandNumber = elem.attribute( "band", "-1" ).toInt();
65  int nColors = 0;
66  QRgb* colors = 0;
67 
68  QDomElement paletteElem = elem.firstChildElement( "colorPalette" );
69  if ( !paletteElem.isNull() )
70  {
71  QDomNodeList paletteEntries = paletteElem.elementsByTagName( "paletteEntry" );
72 
73  QDomElement entryElem;
74  int value;
75  nColors = 0;
76 
77  // We cannot believe that data are correct, check first max value
78  for ( int i = 0; i < paletteEntries.size(); ++i )
79  {
80  entryElem = paletteEntries.at( i ).toElement();
81  // Could be written as doubles (with .0000) in old project files
82  value = ( int )entryElem.attribute( "value", "0" ).toDouble();
83  if ( value >= nColors && value <= 10000 ) nColors = value + 1;
84  }
85  QgsDebugMsg( QString( "nColors = %1" ).arg( nColors ) );
86 
87  colors = new QRgb[ nColors ];
88 
89  for ( int i = 0; i < nColors; ++i )
90  {
91  entryElem = paletteEntries.at( i ).toElement();
92  value = ( int )entryElem.attribute( "value", "0" ).toDouble();
93  QgsDebugMsg( entryElem.attribute( "color", "#000000" ) );
94  if ( value >= 0 && value < nColors )
95  {
96  colors[value] = QColor( entryElem.attribute( "color", "#000000" ) ).rgba();
97  }
98  else
99  {
100  QgsDebugMsg( QString( "value %1 out of range" ).arg( value ) );
101  }
102  }
103  }
104  QgsRasterRenderer* r = new QgsPalettedRasterRenderer( input, bandNumber, colors, nColors );
105  r->readXML( elem );
106  return r;
107 }
108 
110 {
111  if ( mNColors < 1 )
112  {
113  return 0;
114  }
115  QColor* colorArray = new QColor[ mNColors ];
116  for ( int i = 0; i < mNColors; ++i )
117  {
118  colorArray[i] = QColor( mColors[i] );
119  }
120  return colorArray;
121 }
122 
124 {
125  if ( mNColors < 1 )
126  {
127  return 0;
128  }
129  QRgb* rgbValues = new QRgb[mNColors];
130  for ( int i = 0; i < mNColors; ++i )
131  {
132  rgbValues[i] = mColors[i];
133  }
134  return rgbValues;
135 }
136 
137 QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
138 {
139  QgsRasterBlock *outputBlock = new QgsRasterBlock();
140  if ( !mInput )
141  {
142  return outputBlock;
143  }
144 
145  QgsRasterBlock *inputBlock = mInput->block( bandNo, extent, width, height );
146 
147  if ( !inputBlock || inputBlock->isEmpty() )
148  {
149  QgsDebugMsg( "No raster data!" );
150  delete inputBlock;
151  return outputBlock;
152  }
153 
154  double currentOpacity = mOpacity;
155 
156  //rendering is faster without considering user-defined transparency
157  bool hasTransparency = usesTransparency();
158  QgsRasterBlock *alphaBlock = 0;
159 
160  if ( mAlphaBand > 0 && mAlphaBand != mBand )
161  {
162  alphaBlock = mInput->block( mAlphaBand, extent, width, height );
163  if ( !alphaBlock || alphaBlock->isEmpty() )
164  {
165  delete inputBlock;
166  delete alphaBlock;
167  return outputBlock;
168  }
169  }
170  else if ( mAlphaBand == mBand )
171  {
172  alphaBlock = inputBlock;
173  }
174 
175  if ( !outputBlock->reset( QGis::ARGB32_Premultiplied, width, height ) )
176  {
177  delete inputBlock;
178  delete alphaBlock;
179  return outputBlock;
180  }
181 
182  QRgb myDefaultColor = NODATA_COLOR;
183 
184  //use direct data access instead of QgsRasterBlock::setValue
185  //because of performance
186  unsigned int* outputData = ( unsigned int* )( outputBlock->bits() );
187 
188  size_t rasterSize = ( size_t )width * height;
189  for ( size_t i = 0; i < rasterSize; ++i )
190  {
191  if ( inputBlock->isNoData( i ) )
192  {
193  outputData[i] = myDefaultColor;
194  continue;
195  }
196  int val = ( int ) inputBlock->value( i );
197  if ( !hasTransparency )
198  {
199  outputData[i] = mColors[val];
200  }
201  else
202  {
203  currentOpacity = mOpacity;
204  if ( mRasterTransparency )
205  {
206  currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0;
207  }
208  if ( mAlphaBand > 0 )
209  {
210  currentOpacity *= alphaBlock->value( i ) / 255.0;
211  }
212  QColor currentColor = QColor( mColors[val] );
213  outputData[i] = qRgba( currentOpacity * currentColor.red(), currentOpacity * currentColor.green(), currentOpacity * currentColor.blue(), currentOpacity * 255 );
214  }
215  }
216 
217  delete inputBlock;
218  if ( mAlphaBand > 0 && mBand != mAlphaBand )
219  {
220  delete alphaBlock;
221  }
222 
223  return outputBlock;
224 }
225 
226 void QgsPalettedRasterRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
227 {
228  if ( parentElem.isNull() )
229  {
230  return;
231  }
232 
233  QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" );
234  _writeXML( doc, rasterRendererElem );
235 
236  rasterRendererElem.setAttribute( "band", mBand );
237  QDomElement colorPaletteElem = doc.createElement( "colorPalette" );
238  for ( int i = 0; i < mNColors; ++i )
239  {
240  QDomElement colorElem = doc.createElement( "paletteEntry" );
241  colorElem.setAttribute( "value", i );
242  colorElem.setAttribute( "color", QColor( mColors[i] ).name() );
243  colorPaletteElem.appendChild( colorElem );
244  }
245  rasterRendererElem.appendChild( colorPaletteElem );
246 
247  parentElem.appendChild( rasterRendererElem );
248 }
249 
250 void QgsPalettedRasterRenderer::legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const
251 {
252  for ( int i = 0; i < mNColors; ++i )
253  {
254  symbolItems.push_back( qMakePair( QString::number( i ), QColor( mColors[i] ) ) );
255  }
256 }
257 
259 {
260  QList<int> bandList;
261  if ( mBand != -1 )
262  {
263  bandList << mBand;
264  }
265  return bandList;
266 }