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