QGIS API Documentation  3.8.0-Zanzibar (11aff65)
qgsmultibandcolorrendererwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmultibandcolorrendererwidget.cpp
3  -----------------------------------
4  begin : February 2012
5  copyright : (C) 2012 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 
20 #include "qgsrasterlayer.h"
21 #include "qgsrasterdataprovider.h"
22 #include "qgsrasterminmaxwidget.h"
23 
25  : QgsRasterRendererWidget( layer, extent )
26  , mDisableMinMaxWidgetRefresh( false )
27 {
28  setupUi( this );
29  connect( mRedMinLineEdit, &QLineEdit::textChanged, this, &QgsMultiBandColorRendererWidget::mRedMinLineEdit_textChanged );
30  connect( mRedMaxLineEdit, &QLineEdit::textChanged, this, &QgsMultiBandColorRendererWidget::mRedMaxLineEdit_textChanged );
31  connect( mGreenMinLineEdit, &QLineEdit::textChanged, this, &QgsMultiBandColorRendererWidget::mGreenMinLineEdit_textChanged );
32  connect( mGreenMaxLineEdit, &QLineEdit::textChanged, this, &QgsMultiBandColorRendererWidget::mGreenMaxLineEdit_textChanged );
33  connect( mBlueMinLineEdit, &QLineEdit::textChanged, this, &QgsMultiBandColorRendererWidget::mBlueMinLineEdit_textChanged );
34  connect( mBlueMaxLineEdit, &QLineEdit::textChanged, this, &QgsMultiBandColorRendererWidget::mBlueMaxLineEdit_textChanged );
35  createValidators();
36 
37  if ( mRasterLayer )
38  {
40  if ( !provider )
41  {
42  return;
43  }
44 
45  mMinMaxWidget = new QgsRasterMinMaxWidget( layer, this );
46  mMinMaxWidget->setExtent( extent );
47  mMinMaxWidget->setMapCanvas( mCanvas );
48  QHBoxLayout *layout = new QHBoxLayout();
49  layout->setContentsMargins( 0, 0, 0, 0 );
50  mMinMaxContainerWidget->setLayout( layout );
51  layout->addWidget( mMinMaxWidget );
52 
53  connect( mMinMaxWidget, &QgsRasterMinMaxWidget::widgetChanged,
55  connect( mMinMaxWidget, &QgsRasterMinMaxWidget::load,
57 
58  connect( mRedBandComboBox, &QgsRasterBandComboBox::bandChanged,
59  this, &QgsMultiBandColorRendererWidget::onBandChanged );
60  connect( mGreenBandComboBox, &QgsRasterBandComboBox::bandChanged,
61  this, &QgsMultiBandColorRendererWidget::onBandChanged );
62  connect( mBlueBandComboBox, &QgsRasterBandComboBox::bandChanged,
63  this, &QgsMultiBandColorRendererWidget::onBandChanged );
64 
65  mRedBandComboBox->setShowNotSetOption( true );
66  mGreenBandComboBox->setShowNotSetOption( true );
67  mBlueBandComboBox->setShowNotSetOption( true );
68  mRedBandComboBox->setLayer( mRasterLayer );
69  mGreenBandComboBox->setLayer( mRasterLayer );
70  mBlueBandComboBox->setLayer( mRasterLayer );
71 
72  //contrast enhancement algorithms
73  mContrastEnhancementAlgorithmComboBox->addItem( tr( "No enhancement" ), QgsContrastEnhancement::NoEnhancement );
74  mContrastEnhancementAlgorithmComboBox->addItem( tr( "Stretch to MinMax" ), QgsContrastEnhancement::StretchToMinimumMaximum );
75  mContrastEnhancementAlgorithmComboBox->addItem( tr( "Stretch and clip to MinMax" ), QgsContrastEnhancement::StretchAndClipToMinimumMaximum );
76  mContrastEnhancementAlgorithmComboBox->addItem( tr( "Clip to MinMax" ), QgsContrastEnhancement::ClipToMinimumMaximum );
77 
79  onBandChanged( 0 ); // reset mMinMaxWidget bands
80 
81  connect( mContrastEnhancementAlgorithmComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterRendererWidget::widgetChanged );
82  }
83 }
84 
86 {
87  if ( !mRasterLayer )
88  {
89  return nullptr;
90  }
92  if ( !provider )
93  {
94  return nullptr;
95  }
96 
97  int redBand = mRedBandComboBox->currentBand();
98  int greenBand = mGreenBandComboBox->currentBand();
99  int blueBand = mBlueBandComboBox->currentBand();
100 
101  QgsMultiBandColorRenderer *r = new QgsMultiBandColorRenderer( provider, redBand, greenBand, blueBand );
102  setCustomMinMaxValues( r, provider, redBand, greenBand, blueBand );
103 
104  r->setMinMaxOrigin( mMinMaxWidget->minMaxOrigin() );
105 
106  return r;
107 }
108 
110 {
111  mMinMaxWidget->doComputations();
112 }
113 
115 {
117  mMinMaxWidget->setMapCanvas( canvas );
118 }
119 
120 void QgsMultiBandColorRendererWidget::createValidators()
121 {
122  mRedMinLineEdit->setValidator( new QDoubleValidator( mRedMinLineEdit ) );
123  mRedMaxLineEdit->setValidator( new QDoubleValidator( mRedMinLineEdit ) );
124  mGreenMinLineEdit->setValidator( new QDoubleValidator( mGreenMinLineEdit ) );
125  mGreenMaxLineEdit->setValidator( new QDoubleValidator( mGreenMinLineEdit ) );
126  mBlueMinLineEdit->setValidator( new QDoubleValidator( mBlueMinLineEdit ) );
127  mBlueMaxLineEdit->setValidator( new QDoubleValidator( mBlueMinLineEdit ) );
128 }
129 
130 void QgsMultiBandColorRendererWidget::setCustomMinMaxValues( QgsMultiBandColorRenderer *r,
131  const QgsRasterDataProvider *provider,
132  int redBand, int greenBand, int blueBand )
133 {
134  if ( !r || !provider )
135  {
136  return;
137  }
138 
139  if ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ==
141  {
142  r->setRedContrastEnhancement( nullptr );
143  r->setGreenContrastEnhancement( nullptr );
144  r->setBlueContrastEnhancement( nullptr );
145  return;
146  }
147 
148  QgsContrastEnhancement *redEnhancement = nullptr;
149  QgsContrastEnhancement *greenEnhancement = nullptr;
150  QgsContrastEnhancement *blueEnhancement = nullptr;
151 
152  bool redMinOk, redMaxOk;
153  double redMin = mRedMinLineEdit->text().toDouble( &redMinOk );
154  double redMax = mRedMaxLineEdit->text().toDouble( &redMaxOk );
155  if ( redMinOk && redMaxOk && redBand != -1 )
156  {
157  redEnhancement = new QgsContrastEnhancement( ( Qgis::DataType )(
158  provider->dataType( redBand ) ) );
159  redEnhancement->setMinimumValue( redMin );
160  redEnhancement->setMaximumValue( redMax );
161  }
162 
163  bool greenMinOk, greenMaxOk;
164  double greenMin = mGreenMinLineEdit->text().toDouble( &greenMinOk );
165  double greenMax = mGreenMaxLineEdit->text().toDouble( &greenMaxOk );
166  if ( greenMinOk && greenMaxOk && greenBand != -1 )
167  {
168  greenEnhancement = new QgsContrastEnhancement( ( Qgis::DataType )(
169  provider->dataType( greenBand ) ) );
170  greenEnhancement->setMinimumValue( greenMin );
171  greenEnhancement->setMaximumValue( greenMax );
172  }
173 
174  bool blueMinOk, blueMaxOk;
175  double blueMin = mBlueMinLineEdit->text().toDouble( &blueMinOk );
176  double blueMax = mBlueMaxLineEdit->text().toDouble( &blueMaxOk );
177  if ( blueMinOk && blueMaxOk && blueBand != -1 )
178  {
179  blueEnhancement = new QgsContrastEnhancement( ( Qgis::DataType )(
180  provider->dataType( blueBand ) ) );
181  blueEnhancement->setMinimumValue( blueMin );
182  blueEnhancement->setMaximumValue( blueMax );
183  }
184 
185  if ( redEnhancement )
186  {
188  ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) );
189  }
190  if ( greenEnhancement )
191  {
193  ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) );
194  }
195  if ( blueEnhancement )
196  {
198  ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) );
199  }
200  r->setRedContrastEnhancement( redEnhancement );
201  r->setGreenContrastEnhancement( greenEnhancement );
202  r->setBlueContrastEnhancement( blueEnhancement );
203 }
204 
205 void QgsMultiBandColorRendererWidget::onBandChanged( int index )
206 {
207  Q_UNUSED( index )
208 
209  QList<int> myBands;
210  myBands.append( mRedBandComboBox->currentBand() );
211  myBands.append( mGreenBandComboBox->currentBand() );
212  myBands.append( mBlueBandComboBox->currentBand() );
213  mMinMaxWidget->setBands( myBands );
214  emit widgetChanged();
215 }
216 
217 void QgsMultiBandColorRendererWidget::mRedMinLineEdit_textChanged( const QString & )
218 {
219  minMaxModified();
220 }
221 
222 void QgsMultiBandColorRendererWidget::mRedMaxLineEdit_textChanged( const QString & )
223 {
224  minMaxModified();
225 }
226 
227 void QgsMultiBandColorRendererWidget::mGreenMinLineEdit_textChanged( const QString & )
228 {
229  minMaxModified();
230 }
231 
232 void QgsMultiBandColorRendererWidget::mGreenMaxLineEdit_textChanged( const QString & )
233 {
234  minMaxModified();
235 }
236 
237 void QgsMultiBandColorRendererWidget::mBlueMinLineEdit_textChanged( const QString & )
238 {
239  minMaxModified();
240 }
241 
242 void QgsMultiBandColorRendererWidget::mBlueMaxLineEdit_textChanged( const QString & )
243 {
244  minMaxModified();
245 }
246 
247 void QgsMultiBandColorRendererWidget::minMaxModified()
248 {
249  if ( !mDisableMinMaxWidgetRefresh )
250  {
251  if ( ( QgsContrastEnhancement::ContrastEnhancementAlgorithm )( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) == QgsContrastEnhancement::NoEnhancement )
252  {
253  mContrastEnhancementAlgorithmComboBox->setCurrentIndex(
254  mContrastEnhancementAlgorithmComboBox->findData( ( int ) QgsContrastEnhancement::StretchToMinimumMaximum ) );
255  }
256  mMinMaxWidget->userHasSetManualMinMaxValues();
257  emit widgetChanged();
258  }
259 }
260 
261 void QgsMultiBandColorRendererWidget::loadMinMax( int bandNo, double min, double max )
262 {
263  QgsDebugMsg( QStringLiteral( "theBandNo = %1 min = %2 max = %3" ).arg( bandNo ).arg( min ).arg( max ) );
264 
265  QLineEdit *myMinLineEdit, *myMaxLineEdit;
266 
267  if ( mRedBandComboBox->currentBand() == bandNo )
268  {
269  myMinLineEdit = mRedMinLineEdit;
270  myMaxLineEdit = mRedMaxLineEdit;
271  }
272  else if ( mGreenBandComboBox->currentBand() == bandNo )
273  {
274  myMinLineEdit = mGreenMinLineEdit;
275  myMaxLineEdit = mGreenMaxLineEdit;
276  }
277  else if ( mBlueBandComboBox->currentBand() == bandNo )
278  {
279  myMinLineEdit = mBlueMinLineEdit;
280  myMaxLineEdit = mBlueMaxLineEdit;
281  }
282  else // should not happen
283  {
284  QgsDebugMsg( QStringLiteral( "Band not found" ) );
285  return;
286  }
287 
288  mDisableMinMaxWidgetRefresh = true;
289  if ( std::isnan( min ) )
290  {
291  myMinLineEdit->clear();
292  }
293  else
294  {
295  myMinLineEdit->setText( QString::number( min ) );
296  }
297 
298  if ( std::isnan( max ) )
299  {
300  myMaxLineEdit->clear();
301  }
302  else
303  {
304  myMaxLineEdit->setText( QString::number( max ) );
305  }
306  mDisableMinMaxWidgetRefresh = false;
307 }
308 
309 void QgsMultiBandColorRendererWidget::setMinMaxValue( const QgsContrastEnhancement *ce, QLineEdit *minEdit, QLineEdit *maxEdit )
310 {
311  if ( !minEdit || !maxEdit )
312  {
313  return;
314  }
315 
316  if ( !ce )
317  {
318  minEdit->clear();
319  maxEdit->clear();
320  return;
321  }
322 
323  minEdit->setText( QString::number( ce->minimumValue() ) );
324  maxEdit->setText( QString::number( ce->maximumValue() ) );
325 
326  // QgsMultiBandColorRenderer is using individual contrast enhancements for each
327  // band, but this widget GUI has one for all
328  mContrastEnhancementAlgorithmComboBox->setCurrentIndex( mContrastEnhancementAlgorithmComboBox->findData(
329  ( int )( ce->contrastEnhancementAlgorithm() ) ) );
330 }
331 
333 {
334  const QgsMultiBandColorRenderer *mbcr = dynamic_cast<const QgsMultiBandColorRenderer *>( r );
335  if ( mbcr )
336  {
337  mRedBandComboBox->setBand( mbcr->redBand() );
338  mGreenBandComboBox->setBand( mbcr->greenBand() );
339  mBlueBandComboBox->setBand( mbcr->blueBand() );
340 
341  mDisableMinMaxWidgetRefresh = true;
342  setMinMaxValue( mbcr->redContrastEnhancement(), mRedMinLineEdit, mRedMaxLineEdit );
343  setMinMaxValue( mbcr->greenContrastEnhancement(), mGreenMinLineEdit, mGreenMaxLineEdit );
344  setMinMaxValue( mbcr->blueContrastEnhancement(), mBlueMinLineEdit, mBlueMaxLineEdit );
345  mDisableMinMaxWidgetRefresh = false;
346 
347  mMinMaxWidget->setFromMinMaxOrigin( mbcr->minMaxOrigin() );
348  }
349  else
350  {
351  if ( mRedBandComboBox->findText( tr( "Red" ) ) > -1 && mRedBandComboBox->findText( tr( "Green" ) ) > -1 &&
352  mRedBandComboBox->findText( tr( "Blue" ) ) > -1 )
353  {
354  mRedBandComboBox->setCurrentIndex( mRedBandComboBox->findText( tr( "Red" ) ) );
355  mGreenBandComboBox->setCurrentIndex( mGreenBandComboBox->findText( tr( "Green" ) ) );
356  mBlueBandComboBox->setCurrentIndex( mBlueBandComboBox->findText( tr( "Blue" ) ) );
357  }
358  else
359  {
360  mRedBandComboBox->setCurrentIndex( mRedBandComboBox->count() > 1 ? 1 : 0 );
361  mGreenBandComboBox->setCurrentIndex( mRedBandComboBox->count() > 2 ? 2 : 0 );
362  mBlueBandComboBox->setCurrentIndex( mRedBandComboBox->count() > 3 ? 3 : 0 );
363  }
364  }
365 }
366 
368 {
369  switch ( index )
370  {
371  case 0:
372  return mRedMinLineEdit->text();
373  case 1:
374  return mGreenMinLineEdit->text();
375  case 2:
376  return mBlueMinLineEdit->text();
377  default:
378  break;
379  }
380  return QString();
381 }
382 
384 {
385  switch ( index )
386  {
387  case 0:
388  return mRedMaxLineEdit->text();
389  case 1:
390  return mGreenMaxLineEdit->text();
391  case 2:
392  return mBlueMaxLineEdit->text();
393  default:
394  break;
395  }
396  return QString();
397 }
398 
399 void QgsMultiBandColorRendererWidget::setMin( const QString &value, int index )
400 {
401  mDisableMinMaxWidgetRefresh = true;
402  switch ( index )
403  {
404  case 0:
405  mRedMinLineEdit->setText( value );
406  break;
407  case 1:
408  mGreenMinLineEdit->setText( value );
409  break;
410  case 2:
411  mBlueMinLineEdit->setText( value );
412  break;
413  default:
414  break;
415  }
416  mDisableMinMaxWidgetRefresh = false;
417 }
418 
419 void QgsMultiBandColorRendererWidget::setMax( const QString &value, int index )
420 {
421  mDisableMinMaxWidgetRefresh = true;
422  switch ( index )
423  {
424  case 0:
425  mRedMaxLineEdit->setText( value );
426  break;
427  case 1:
428  mGreenMaxLineEdit->setText( value );
429  break;
430  case 2:
431  mBlueMaxLineEdit->setText( value );
432  break;
433  default:
434  break;
435  }
436  mDisableMinMaxWidgetRefresh = false;
437 }
438 
440 {
441  switch ( index )
442  {
443  case 0:
444  return mRedBandComboBox->currentBand();
445  case 1:
446  return mGreenBandComboBox->currentBand();
447  case 2:
448  return mBlueBandComboBox->currentBand();
449  default:
450  break;
451  }
452  return -1;
453 }
void setExtent(const QgsRectangle &extent)
Sets the extent to use for minimum and maximum value calculation.
double maximumValue() const
Returns the maximum value for the contrast enhancement range.
void setFromRenderer(const QgsRasterRenderer *r)
A rectangle specified with double values.
Definition: qgsrectangle.h:41
void setMapCanvas(QgsMapCanvas *canvas) override
Sets the map canvas associated with the widget.
const QgsContrastEnhancement * blueContrastEnhancement() const
void setMinimumValue(double value, bool generateTable=true)
Sets the minimum value for the contrast enhancement range.
QgsMultiBandColorRendererWidget(QgsRasterLayer *layer, const QgsRectangle &extent=QgsRectangle())
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
DataType
Raster data types.
Definition: qgis.h:79
double minimumValue() const
Returns the minimum value for the contrast enhancement range.
QgsRasterMinMaxOrigin minMaxOrigin()
Returns a QgsRasterMinMaxOrigin object with the widget values.
const QgsRasterMinMaxOrigin & minMaxOrigin() const
Returns const reference to origin of min/max values.
QgsRasterRenderer * renderer() const
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:73
void setGreenContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void setMax(const QString &value, int index=0) override
void widgetChanged()
Emitted when something on the widget has changed.
void setMin(const QString &value, int index=0) override
QgsRasterDataProvider * dataProvider() override
Returns the layer&#39;s data provider, it may be nullptr.
void setRedContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
void setMaximumValue(double value, bool generateTable=true)
Sets the maximum value for the contrast enhancement range.
void bandChanged(int band)
Emitted when the currently selected band changes.
void setBands(const QList< int > &bands)
void loadMinMax(int bandNo, double min, double max)
called when new min/max values are loaded
void setMinMaxOrigin(const QgsRasterMinMaxOrigin &origin)
Sets origin of min/max values.
void userHasSetManualMinMaxValues()
Uncheck cumulative cut, min/max, std-dev radio buttons.
ContrastEnhancementAlgorithm
This enumerator describes the types of contrast enhancement algorithms that can be used...
const QgsContrastEnhancement * redContrastEnhancement() const
const QgsContrastEnhancement * greenContrastEnhancement() const
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void setBlueContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Renderer for multiband images with the color components.
Manipulates raster pixel values so that they enhanceContrast or clip into a specified numerical range...
void load(int bandNo, double min, double max)
signal emitted when new min/max values are computed from statistics.
QgsMapCanvas * mCanvas
Associated map canvas.
void widgetChanged()
Emitted when something on the widget has changed.
void doComputations() override
Load programmatically with current values.
Raster renderer pipe that applies colors to a raster.
void setContrastEnhancementAlgorithm(ContrastEnhancementAlgorithm algorithm, bool generateTable=true)
Sets the contrast enhancement algorithm.
void doComputations()
Load programmatically with current values.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
Base class for raster data providers.
void setFromMinMaxOrigin(const QgsRasterMinMaxOrigin &)
Sets the "source" of min/max values.