QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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 {
38  renderer->setOpacity( mOpacity );
39  renderer->setAlphaBand( mAlphaBand );
41  renderer->setGradient( mGradient );
43  {
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;
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 ( size_t i = 0; i < ( size_t )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  {
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 {
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 }