26 #include "qgssettings.h"
34 #include <qwt_global.h>
35 #include <qwt_plot_canvas.h>
36 #include <qwt_legend.h>
38 #include <qwt_plot_curve.h>
39 #include <qwt_plot_grid.h>
40 #include <qwt_plot_marker.h>
41 #include <qwt_plot_picker.h>
42 #include <qwt_picker_machine.h>
43 #include <qwt_plot_zoomer.h>
44 #include <qwt_plot_layout.h>
45 #include <qwt_plot_renderer.h>
46 #include <qwt_plot_histogram.h>
60 connect( mSaveAsImageButton, &QToolButton::clicked,
this, &QgsRasterHistogramWidget::mSaveAsImageButton_clicked );
61 connect( cboHistoBand,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsRasterHistogramWidget::cboHistoBand_currentIndexChanged );
62 connect( btnHistoMin, &QToolButton::toggled,
this, &QgsRasterHistogramWidget::btnHistoMin_toggled );
63 connect( btnHistoMax, &QToolButton::toggled,
this, &QgsRasterHistogramWidget::btnHistoMax_toggled );
64 connect( btnHistoCompute, &QPushButton::clicked,
this, &QgsRasterHistogramWidget::btnHistoCompute_clicked );
68 mRendererWidget =
nullptr;
69 mRendererName = QStringLiteral(
"singlebandgray" );
74 mHistoPicker =
nullptr;
75 mHistoZoomer =
nullptr;
76 mHistoMarkerMin =
nullptr;
77 mHistoMarkerMax =
nullptr;
80 mHistoShowMarkers = settings.value( QStringLiteral(
"Raster/histogram/showMarkers" ),
false ).toBool();
82 mHistoZoomToMinMax = settings.value( QStringLiteral(
"Raster/histogram/zoomToMinMax" ),
false ).toBool();
83 mHistoUpdateStyleToMinMax = settings.value( QStringLiteral(
"Raster/histogram/updateStyleToMinMax" ),
true ).toBool();
84 mHistoDrawLines = settings.value( QStringLiteral(
"Raster/histogram/drawLines" ),
true ).toBool();
86 mHistoShowBands = ShowAll;
92 int myBandCountInt = mRasterLayer->
bandCount();
93 for (
int myIteratorInt = 1;
94 myIteratorInt <= myBandCountInt;
97 cboHistoBand->addItem( mRasterLayer->
bandName( myIteratorInt ) );
113 connect( leHistoMin, &QLineEdit::editingFinished,
this, &QgsRasterHistogramWidget::applyHistoMin );
114 connect( leHistoMax, &QLineEdit::editingFinished,
this, &QgsRasterHistogramWidget::applyHistoMax );
118 QMenu *menu =
new QMenu(
this );
119 menu->setSeparatorsCollapsible(
false );
120 btnHistoActions->setMenu( menu );
121 QActionGroup *group =
nullptr;
122 QAction *action =
nullptr;
125 group =
new QActionGroup(
this );
126 group->setExclusive(
false );
127 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
128 action =
new QAction( tr(
"Min/Max options" ), group );
129 action->setSeparator(
true );
130 menu->addAction( action );
131 action =
new QAction( tr(
"Always show min/max markers" ), group );
132 action->setData( QVariant(
"Show markers" ) );
133 action->setCheckable(
true );
134 action->setChecked( mHistoShowMarkers );
135 menu->addAction( action );
136 action =
new QAction( tr(
"Zoom to min/max" ), group );
137 action->setData( QVariant(
"Zoom min_max" ) );
138 action->setCheckable(
true );
139 action->setChecked( mHistoZoomToMinMax );
140 menu->addAction( action );
141 action =
new QAction( tr(
"Update style to min/max" ), group );
142 action->setData( QVariant(
"Update min_max" ) );
143 action->setCheckable(
true );
144 action->setChecked( mHistoUpdateStyleToMinMax );
145 menu->addAction( action );
148 group =
new QActionGroup(
this );
149 group->setExclusive(
false );
150 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
151 action =
new QAction( tr(
"Visibility" ), group );
152 action->setSeparator(
true );
153 menu->addAction( action );
154 group =
new QActionGroup(
this );
155 group->setExclusive(
true );
156 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
157 action =
new QAction( tr(
"Show all bands" ), group );
158 action->setData( QVariant(
"Show all" ) );
159 action->setCheckable(
true );
160 action->setChecked( mHistoShowBands == ShowAll );
161 menu->addAction( action );
162 action =
new QAction( tr(
"Show RGB/Gray band(s)" ), group );
163 action->setData( QVariant(
"Show RGB" ) );
164 action->setCheckable(
true );
165 action->setChecked( mHistoShowBands == ShowRGB );
166 menu->addAction( action );
167 action =
new QAction( tr(
"Show selected band" ), group );
168 action->setData( QVariant(
"Show selected" ) );
169 action->setCheckable(
true );
170 action->setChecked( mHistoShowBands == ShowSelected );
171 menu->addAction( action );
174 group =
new QActionGroup(
this );
175 group->setExclusive(
false );
176 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
177 action =
new QAction( tr(
"Display" ), group );
178 action->setSeparator(
true );
179 menu->addAction( action );
181 action =
new QAction( QString(), group );
182 action->setData( QVariant(
"Draw lines" ) );
185 action->setText( tr(
"Draw as lines" ) );
186 action->setCheckable(
true );
187 action->setChecked( mHistoDrawLines );
191 action->setText( tr(
"Draw as lines (only int layers)" ) );
192 action->setEnabled(
false );
194 menu->addAction( action );
197 action =
new QAction( tr(
"Actions" ), group );
198 action->setSeparator(
true );
199 menu->addAction( action );
202 group =
new QActionGroup(
this );
203 group->setExclusive(
false );
204 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
205 action =
new QAction( tr(
"Reset" ), group );
206 action->setData( QVariant(
"Load reset" ) );
207 menu->addAction( action );
213 action =
new QAction( tr(
"Load min/max" ), group );
214 action->setSeparator(
true );
215 menu->addAction( action );
216 action =
new QAction( tr(
"Estimate (faster)" ), group );
217 action->setData( QVariant(
"Load estimate" ) );
218 menu->addAction( action );
219 action =
new QAction( tr(
"Actual (slower)" ), group );
220 action->setData( QVariant(
"Load actual" ) );
221 menu->addAction( action );
222 action =
new QAction( tr(
"Current extent" ), group );
223 action->setData( QVariant(
"Load extent" ) );
224 menu->addAction( action );
225 action =
new QAction( tr(
"Use stddev (1.0)" ), group );
226 action->setData( QVariant(
"Load 1 stddev" ) );
227 menu->addAction( action );
228 action =
new QAction( tr(
"Use stddev (custom)" ), group );
229 action->setData( QVariant(
"Load stddev" ) );
230 menu->addAction( action );
231 action =
new QAction( tr(
"Load for each band" ), group );
232 action->setData( QVariant(
"Load apply all" ) );
233 action->setCheckable(
true );
234 action->setChecked( mHistoLoadApplyAll );
235 menu->addAction( action );
239 action =
new QAction( tr(
"Recompute Histogram" ), group );
240 action->setData( QVariant(
"Compute histogram" ) );
241 menu->addAction( action );
249 mRendererName = name;
250 mRendererWidget = rendererWidget;
252 cboHistoBand_currentIndexChanged( -1 );
260 cboHistoBand_currentIndexChanged( -1 );
264 if ( QApplication::overrideCursor() )
265 QApplication::restoreOverrideCursor();
266 btnHistoMin->setChecked(
false );
267 btnHistoMax->setChecked(
false );
271 void QgsRasterHistogramWidget::btnHistoCompute_clicked()
300 xRes = yRes = std::sqrt( (
static_cast<double>( extent.width( ) ) * extent.height() ) / sampleSize );
305 const double srcXRes = extent.width() / rasterInterface->
xSize();
306 const double srcYRes = extent.height() / rasterInterface->
ySize();
307 if ( xRes < srcXRes ) xRes = srcXRes;
308 if ( yRes < srcYRes ) yRes = srcYRes;
311 const int histogramWidth =
static_cast <int>( extent.width() / xRes );
312 const int histogramHeight =
static_cast <int>( extent.height() / yRes );
314 int binCount =
static_cast<int>( std::min(
static_cast<qint64
>( 1000 ),
315 static_cast<qint64
>( histogramWidth ) * histogramHeight ) );
320 binCount =
static_cast<int>( std::min(
static_cast<qint64
>( binCount ),
321 static_cast<qint64
>( std::ceil( statsMax - statsMin + 1 ) ) ) );
332 int myBandCountInt = mRasterLayer->
bandCount();
335 if ( ! forceComputeFlag )
337 for (
int myIteratorInt = 1;
338 myIteratorInt <= myBandCountInt;
342 const int binCount = getBinCount( mRasterLayer->
dataProvider(), myIteratorInt, sampleSize );
343 if ( !mRasterLayer->
dataProvider()->
hasHistogram( myIteratorInt, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(),
QgsRectangle(), sampleSize ) )
345 QgsDebugMsg( QStringLiteral(
"band %1 does not have cached histo" ).arg( myIteratorInt ) );
352 stackedWidget2->setCurrentIndex( 1 );
356 QApplication::setOverrideCursor( Qt::WaitCursor );
358 for (
int myIteratorInt = 1;
359 myIteratorInt <= myBandCountInt;
363 const int binCount = getBinCount( mRasterLayer->
dataProvider(), myIteratorInt, sampleSize );
364 mRasterLayer->
dataProvider()->
histogram( myIteratorInt, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(),
QgsRectangle(), sampleSize,
false, feedback.get() );
368 stackedWidget2->setCurrentIndex( 0 );
369 QApplication::restoreOverrideCursor();
386 int myBandCountInt = mRasterLayer->
bandCount();
391 QgsDebugMsg( QStringLiteral(
"raster does not have cached histogram" ) );
392 stackedWidget2->setCurrentIndex( 2 );
397 mpPlot->detachItems();
400 mpPlot->setAutoDelete(
true );
401 mpPlot->setTitle( QObject::tr(
"Raster Histogram" ) );
402 mpPlot->insertLegend(
new QwtLegend(), QwtPlot::BottomLegend );
404 mpPlot->setAxisTitle( QwtPlot::xBottom, QObject::tr(
"Pixel Value" ) );
405 mpPlot->setAxisTitle( QwtPlot::yLeft, QObject::tr(
"Frequency" ) );
406 mpPlot->setAxisAutoScale( QwtPlot::yLeft );
410 QwtPlotGrid *myGrid =
new QwtPlotGrid();
411 myGrid->attach( mpPlot );
414 mHistoColors.clear();
415 mHistoColors << Qt::black;
416 QVector<QColor> myColors;
417 myColors << Qt::red << Qt::green << Qt::blue << Qt::magenta << Qt::darkYellow << Qt::cyan;
418 qsrand( myBandCountInt * 100 );
419 while ( myColors.size() <= myBandCountInt )
422 QColor( 1 + (
int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) ),
423 1 + (
int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) ),
424 1 + (
int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) ) );
427 qsrand( time(
nullptr ) );
431 QList< int > mySelectedBands = rendererSelectedBands();
432 if ( mRendererName == QLatin1String(
"singlebandgray" ) )
434 int myGrayBand = mySelectedBands[0];
435 for (
int i = 1; i <= myBandCountInt; i++ )
437 if ( i == myGrayBand )
439 mHistoColors << Qt::darkGray;
440 cboHistoBand->setItemData( i - 1, QColor( Qt::darkGray ), Qt::ForegroundRole );
444 if ( ! myColors.isEmpty() )
446 mHistoColors << myColors.first();
447 myColors.pop_front();
451 mHistoColors << Qt::black;
453 cboHistoBand->setItemData( i - 1, QColor( Qt::black ), Qt::ForegroundRole );
458 else if ( mRendererName == QLatin1String(
"multibandcolor" ) )
460 int myRedBand = mySelectedBands[0];
461 int myGreenBand = mySelectedBands[1];
462 int myBlueBand = mySelectedBands[2];
465 myColors.remove( 0, 3 );
466 for (
int i = 1; i <= myBandCountInt; i++ )
469 if ( i == myRedBand )
471 else if ( i == myGreenBand )
473 else if ( i == myBlueBand )
477 if ( ! myColors.isEmpty() )
479 myColor = myColors.first();
480 myColors.pop_front();
486 cboHistoBand->setItemData( i - 1, QColor( Qt::black ), Qt::ForegroundRole );
488 if ( i == myRedBand || i == myGreenBand || i == myBlueBand )
490 cboHistoBand->setItemData( i - 1, myColor, Qt::ForegroundRole );
492 mHistoColors << myColor;
497 mHistoColors << myColors;
512 bool myFirstIteration =
true;
514 mySelectedBands = histoSelectedBands();
515 double myBinXStep = 1;
518 for (
int myIteratorInt = 1;
519 myIteratorInt <= myBandCountInt;
523 if ( mHistoShowBands != ShowAll )
525 if ( ! mySelectedBands.contains( myIteratorInt ) )
534 const int binCount = getBinCount( mRasterLayer->
dataProvider(), myIteratorInt, sampleSize );
537 QgsDebugMsg( QStringLiteral(
"got raster histo for band %1 : min=%2 max=%3 count=%4" ).arg( myIteratorInt ).arg( myHistogram.
minimum ).arg( myHistogram.
maximum ).arg( myHistogram.
binCount ) );
540 bool myDrawLines =
true;
541 if ( ! mHistoDrawLines &&
549 QwtPlotCurve *mypCurve =
nullptr;
552 mypCurve =
new QwtPlotCurve( tr(
"Band %1" ).arg( myIteratorInt ) );
554 mypCurve->setRenderHint( QwtPlotItem::RenderAntialiased );
555 mypCurve->setPen( QPen( mHistoColors.at( myIteratorInt ) ) );
558 QwtPlotHistogram *mypHisto =
nullptr;
561 mypHisto =
new QwtPlotHistogram( tr(
"Band %1" ).arg( myIteratorInt ) );
562 mypHisto->setRenderHint( QwtPlotItem::RenderAntialiased );
564 mypHisto->setPen( QPen( Qt::lightGray ) );
566 mypHisto->setBrush( QBrush( mHistoColors.at( myIteratorInt ) ) );
569 QVector<QPointF> data;
570 QVector<QwtIntervalSample> dataHisto;
576 myBinX = myHistogram.
minimum + myBinXStep / 2.0;
584 for (
int myBin = 0; myBin < myHistogram.
binCount; myBin++ )
589 data << QPointF( myBinX, myBinValue );
593 dataHisto << QwtIntervalSample( myBinValue, myBinX - myBinXStep / 2.0, myBinX + myBinXStep / 2.0 );
595 myBinX += myBinXStep;
600 mypCurve->setSamples( data );
601 mypCurve->attach( mpPlot );
605 mypHisto->setSamples( dataHisto );
606 mypHisto->attach( mpPlot );
609 if ( myFirstIteration || mHistoMin > myHistogram.
minimum )
611 mHistoMin = myHistogram.
minimum;
613 if ( myFirstIteration || mHistoMax < myHistogram.
maximum )
615 mHistoMax = myHistogram.
maximum;
617 QgsDebugMsg( QStringLiteral(
"computed histo min = %1 max = %2" ).arg( mHistoMin ).arg( mHistoMax ) );
618 myFirstIteration =
false;
621 if ( mHistoMin < mHistoMax )
627 mpPlot->setAxisScale( QwtPlot::xBottom,
628 mHistoMin - myBinXStep / 2,
629 mHistoMax + myBinXStep / 2 );
630 mpPlot->setEnabled(
true );
635 mHistoMarkerMin =
new QwtPlotMarker();
636 mHistoMarkerMin->attach( mpPlot );
637 mHistoMarkerMax =
new QwtPlotMarker();
638 mHistoMarkerMax->attach( mpPlot );
639 updateHistoMarkers();
644 mHistoPicker =
new QwtPlotPicker( mpPlot->canvas() );
646 mHistoPicker->setTrackerMode( QwtPicker::AlwaysOff );
647 mHistoPicker->setRubberBand( QwtPicker::VLineRubberBand );
648 mHistoPicker->setStateMachine(
new QwtPickerDragPointMachine );
649 connect( mHistoPicker,
static_cast < void ( QwtPlotPicker::* )(
const QPointF & )
> ( &QwtPlotPicker::selected ),
this, &QgsRasterHistogramWidget::histoPickerSelected );
651 mHistoPicker->setEnabled(
false );
656 mHistoZoomer =
new QwtPlotZoomer( mpPlot->canvas() );
657 mHistoZoomer->setStateMachine(
new QwtPickerDragRectMachine );
658 mHistoZoomer->setTrackerMode( QwtPicker::AlwaysOff );
660 mHistoZoomer->setEnabled(
true );
664 mpPlot->setDisabled(
true );
666 mHistoPicker->setEnabled(
false );
668 mHistoZoomer->setEnabled(
false );
671 stackedWidget2->setCurrentIndex( 0 );
675 QApplication::restoreOverrideCursor();
678 void QgsRasterHistogramWidget::mSaveAsImageButton_clicked()
684 QFileInfo myInfo( myFileNameAndFilter.first );
685 if ( !myInfo.baseName().isEmpty() )
692 int width,
int height,
int quality )
695 QFileInfo myInfo( filename );
696 QDir myDir( myInfo.dir() );
697 if ( ! myDir.exists() )
699 QgsDebugMsg( QStringLiteral(
"Error, directory %1 non-existent (theFilename = %2)" ).arg( myDir.absolutePath(), filename ) );
704 QPixmap myPixmap( width, height );
705 QRect myQRect( 5, 5, width - 10, height - 10 );
706 myPixmap.fill( Qt::white );
708 QwtPlotRenderer myRenderer;
709 myRenderer.setDiscardFlags( QwtPlotRenderer::DiscardBackground |
710 QwtPlotRenderer::DiscardCanvasBackground );
711 myRenderer.setLayoutFlags( QwtPlotRenderer::FrameWithScales );
714 myPainter.begin( &myPixmap );
715 myRenderer.render( mpPlot, &myPainter, myQRect );
719 myPixmap.save( filename,
nullptr, quality );
727 cboHistoBand->setCurrentIndex( bandNo - 1 );
730 void QgsRasterHistogramWidget::cboHistoBand_currentIndexChanged(
int index )
732 if ( mHistoShowBands == ShowSelected )
736 index = cboHistoBand->currentIndex();
739 mHistoPicker->setEnabled(
false );
740 mHistoPicker->setRubberBandPen( QPen( mHistoColors.at( index + 1 ) ) );
743 mHistoZoomer->setEnabled(
true );
744 btnHistoMin->setEnabled(
true );
745 btnHistoMax->setEnabled(
true );
747 QPair< QString, QString > myMinMax = rendererMinMax( index + 1 );
748 leHistoMin->setText( myMinMax.first );
749 leHistoMax->setText( myMinMax.second );
755 void QgsRasterHistogramWidget::histoActionTriggered( QAction *action )
759 histoAction( action->data().toString(), action->isChecked() );
764 if ( actionName.isEmpty() )
768 QgsDebugMsg( QStringLiteral(
"band = %1 action = %2" ).arg( cboHistoBand->currentIndex() + 1 ).arg( actionName ) );
771 if ( actionName == QLatin1String(
"Show markers" ) )
773 mHistoShowMarkers = actionFlag;
774 QgsSettings settings;
775 settings.setValue( QStringLiteral(
"Raster/histogram/showMarkers" ), mHistoShowMarkers );
776 updateHistoMarkers();
779 else if ( actionName == QLatin1String(
"Zoom min_max" ) )
781 mHistoZoomToMinMax = actionFlag;
782 QgsSettings settings;
783 settings.setValue( QStringLiteral(
"Raster/histogram/zoomToMinMax" ), mHistoZoomToMinMax );
786 else if ( actionName == QLatin1String(
"Update min_max" ) )
788 mHistoUpdateStyleToMinMax = actionFlag;
789 QgsSettings settings;
790 settings.setValue( QStringLiteral(
"Raster/histogram/updateStyleToMinMax" ), mHistoUpdateStyleToMinMax );
793 else if ( actionName == QLatin1String(
"Show all" ) )
795 mHistoShowBands = ShowAll;
800 else if ( actionName == QLatin1String(
"Show selected" ) )
802 mHistoShowBands = ShowSelected;
807 else if ( actionName == QLatin1String(
"Show RGB" ) )
809 mHistoShowBands = ShowRGB;
814 else if ( actionName == QLatin1String(
"Draw lines" ) )
816 mHistoDrawLines = actionFlag;
817 QgsSettings settings;
818 settings.setValue( QStringLiteral(
"Raster/histogram/drawLines" ), mHistoDrawLines );
819 btnHistoCompute_clicked();
823 else if ( actionName ==
"Load apply all" )
825 mHistoLoadApplyAll = actionFlag;
826 settings.setValue(
"/Raster/histogram/loadApplyAll", mHistoLoadApplyAll );
832 else if ( actionName.left( 5 ) == QLatin1String(
"Load " ) && mRendererWidget )
834 QVector<int> myBands;
838 double minMaxValues[2];
841 if ( mHistoLoadApplyAll )
843 int myBandCountInt = mRasterLayer->
bandCount();
844 for (
int i = 1; i <= myBandCountInt; i++ )
846 if ( i != cboHistoBand->currentIndex() + 1 )
853 myBands << cboHistoBand->currentIndex() + 1;
857 double myStdDev = 1.0;
858 if ( actionName ==
"Load stddev" )
860 myStdDev = mRendererWidget->
stdDev().toDouble();
865 leHistoMin->blockSignals(
true );
866 leHistoMax->blockSignals(
true );
869 const auto constMyBands = myBands;
870 for (
int bandNo : constMyBands )
874 if ( actionName ==
"Load actual" )
876 ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::Actual,
877 bandNo, minMaxValues );
879 else if ( actionName ==
"Load estimate" )
881 ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::Estimate,
882 bandNo, minMaxValues );
884 else if ( actionName ==
"Load extent" )
886 ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::CurrentExtent,
887 bandNo, minMaxValues );
889 else if ( actionName ==
"Load 1 stddev" ||
890 actionName ==
"Load stddev" )
892 ok = mRendererWidget->bandMinMaxFromStdDev( myStdDev, bandNo, minMaxValues );
897 cboHistoBand->setCurrentIndex( bandNo - 1 );
898 if ( !ok || actionName == QLatin1String(
"Load reset" ) )
912 leHistoMin->setText( QString::number( minMaxValues[0] ) );
913 leHistoMax->setText( QString::number( minMaxValues[1] ) );
920 leHistoMin->blockSignals(
false );
921 leHistoMax->blockSignals(
false );
922 updateHistoMarkers();
924 else if ( actionName == QLatin1String(
"Compute histogram" ) )
926 btnHistoCompute_clicked();
935 void QgsRasterHistogramWidget::applyHistoMin()
937 if ( ! mRendererWidget )
940 int bandNo = cboHistoBand->currentIndex() + 1;
941 QList< int > mySelectedBands = rendererSelectedBands();
943 for (
int i = 0; i <= mySelectedBands.size(); i++ )
947 min = leHistoMin->text();
948 if ( mHistoUpdateStyleToMinMax && mRendererWidget->
min( i ) != min )
950 mRendererWidget->
setMin( min, i );
959 updateHistoMarkers();
961 if ( ! min.isEmpty() && mHistoZoomToMinMax && mHistoZoomer )
963 QRectF rect = mHistoZoomer->zoomRect();
964 rect.setLeft( min.toDouble() );
965 mHistoZoomer->zoom( rect );
970 void QgsRasterHistogramWidget::applyHistoMax()
972 if ( ! mRendererWidget )
975 int bandNo = cboHistoBand->currentIndex() + 1;
976 QList< int > mySelectedBands = rendererSelectedBands();
978 for (
int i = 0; i <= mySelectedBands.size(); i++ )
982 max = leHistoMax->text();
983 if ( mHistoUpdateStyleToMinMax && mRendererWidget->
max( i ) != max )
985 mRendererWidget->
setMax( max, i );
994 updateHistoMarkers();
996 if ( ! max.isEmpty() && mHistoZoomToMinMax && mHistoZoomer )
998 QRectF rect = mHistoZoomer->zoomRect();
999 rect.setRight( max.toDouble() );
1000 mHistoZoomer->zoom( rect );
1005 void QgsRasterHistogramWidget::btnHistoMin_toggled()
1007 if ( mpPlot && mHistoPicker )
1009 if ( QApplication::overrideCursor() )
1010 QApplication::restoreOverrideCursor();
1011 if ( btnHistoMin->isChecked() )
1013 btnHistoMax->setChecked(
false );
1014 QApplication::setOverrideCursor( Qt::PointingHandCursor );
1017 mHistoZoomer->setEnabled( ! btnHistoMin->isChecked() );
1018 mHistoPicker->setEnabled( btnHistoMin->isChecked() );
1020 updateHistoMarkers();
1023 void QgsRasterHistogramWidget::btnHistoMax_toggled()
1025 if ( mpPlot && mHistoPicker )
1027 if ( QApplication::overrideCursor() )
1028 QApplication::restoreOverrideCursor();
1029 if ( btnHistoMax->isChecked() )
1031 btnHistoMin->setChecked(
false );
1032 QApplication::setOverrideCursor( Qt::PointingHandCursor );
1035 mHistoZoomer->setEnabled( ! btnHistoMax->isChecked() );
1036 mHistoPicker->setEnabled( btnHistoMax->isChecked() );
1038 updateHistoMarkers();
1045 if ( !scale )
return QString();
1047 QList< double > minorTicks = scale->ticks( QwtScaleDiv::MinorTick );
1048 QList< double > majorTicks = scale->ticks( QwtScaleDiv::MajorTick );
1049 double diff = ( minorTicks[1] - minorTicks[0] ) / div;
1050 double min = majorTicks[0] - diff;
1052 min -= ( majorTicks[1] - majorTicks[0] );
1053 double max = scale->upperBound();
1054 double closest = target;
1055 double current = min;
1057 while ( current < max )
1060 if ( current > target )
1062 closest = ( std::fabs( target - current + diff ) < std::fabs( target - current ) ) ? current - diff : current;
1068 return QString::number( closest );
1071 void QgsRasterHistogramWidget::histoPickerSelected( QPointF pos )
1073 if ( btnHistoMin->isChecked() || btnHistoMax->isChecked() )
1075 const QwtScaleDiv *scale = &mpPlot->axisScaleDiv( QwtPlot::xBottom );
1077 if ( btnHistoMin->isChecked() )
1081 btnHistoMin->setChecked(
false );
1087 btnHistoMax->setChecked(
false );
1090 if ( QApplication::overrideCursor() )
1091 QApplication::restoreOverrideCursor();
1094 void QgsRasterHistogramWidget::histoPickerSelectedQwt5(
QwtDoublePoint pos )
1096 histoPickerSelected( QPointF( pos.x(), pos.y() ) );
1099 void QgsRasterHistogramWidget::updateHistoMarkers()
1102 if ( leHistoMin->signalsBlocked() )
1105 if ( !mpPlot || !mHistoMarkerMin || !mHistoMarkerMax )
1108 int bandNo = cboHistoBand->currentIndex() + 1;
1109 QList< int > mySelectedBands = histoSelectedBands();
1111 if ( ( ! mHistoShowMarkers && ! btnHistoMin->isChecked() && ! btnHistoMax->isChecked() ) ||
1112 ( ! mySelectedBands.isEmpty() && ! mySelectedBands.contains( bandNo ) ) )
1114 mHistoMarkerMin->hide();
1115 mHistoMarkerMax->hide();
1120 double minVal = mHistoMin;
1121 double maxVal = mHistoMax;
1122 QString minStr = leHistoMin->text();
1123 QString maxStr = leHistoMax->text();
1124 if ( !minStr.isEmpty() )
1125 minVal = minStr.toDouble();
1126 if ( !maxStr.isEmpty() )
1127 maxVal = maxStr.toDouble();
1129 QPen linePen = QPen( mHistoColors.at( bandNo ) );
1130 linePen.setStyle( Qt::DashLine );
1131 mHistoMarkerMin->setLineStyle( QwtPlotMarker::VLine );
1132 mHistoMarkerMin->setLinePen( linePen );
1133 mHistoMarkerMin->setXValue( minVal );
1134 mHistoMarkerMin->show();
1135 mHistoMarkerMax->setLineStyle( QwtPlotMarker::VLine );
1136 mHistoMarkerMax->setLinePen( linePen );
1137 mHistoMarkerMax->setXValue( maxVal );
1138 mHistoMarkerMax->show();
1144 QList< int > QgsRasterHistogramWidget::histoSelectedBands()
1146 QList< int > mySelectedBands;
1148 if ( mHistoShowBands != ShowAll )
1150 if ( mHistoShowBands == ShowSelected )
1152 mySelectedBands << cboHistoBand->currentIndex() + 1;
1154 else if ( mHistoShowBands == ShowRGB )
1156 mySelectedBands = rendererSelectedBands();
1160 return mySelectedBands;
1163 QList< int > QgsRasterHistogramWidget::rendererSelectedBands()
1165 QList< int > mySelectedBands;
1167 if ( ! mRendererWidget )
1169 mySelectedBands << -1 << -1 << -1;
1170 return mySelectedBands;
1173 if ( mRendererName == QLatin1String(
"singlebandgray" ) )
1177 else if ( mRendererName == QLatin1String(
"multibandcolor" ) )
1179 for (
int i = 0; i <= 2; i++ )
1185 return mySelectedBands;
1188 QPair< QString, QString > QgsRasterHistogramWidget::rendererMinMax(
int bandNo )
1190 QPair< QString, QString > myMinMax;
1192 if ( ! mRendererWidget )
1195 if ( mRendererName == QLatin1String(
"singlebandgray" ) )
1199 myMinMax.first = mRendererWidget->
min();
1200 myMinMax.second = mRendererWidget->
max();
1203 else if ( mRendererName == QLatin1String(
"multibandcolor" ) )
1205 for (
int i = 0; i <= 2; i++ )
1209 myMinMax.first = mRendererWidget->
min( i );
1210 myMinMax.second = mRendererWidget->
max( i );
1226 if ( myMinMax.first.isEmpty() )
1227 myMinMax.first = QString::number( mHistoMin );
1228 if ( myMinMax.second.isEmpty() )
1229 myMinMax.second = QString::number( mHistoMax );
1231 QgsDebugMsg( QStringLiteral(
"bandNo %1 got min/max [%2] [%3]" ).arg( bandNo ).arg( myMinMax.first, myMinMax.second ) );
DataType
Raster data types.
@ Int16
Sixteen bit signed integer (qint16)
@ UInt16
Sixteen bit unsigned integer (quint16)
@ Byte
Eight bit unsigned integer (quint8)
@ Int32
Thirty two bit signed integer (qint32)
@ UInt32
Thirty two bit unsigned integer (quint32)
static QPixmap getThemePixmap(const QString &name, const QColor &foreColor=QColor(), const QColor &backColor=QColor(), int size=16)
Helper to get a theme icon as a pixmap.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static double maximumValuePossible(Qgis::DataType dataType)
Helper function that returns the maximum possible value for a data type.
static double minimumValuePossible(Qgis::DataType dataType)
Helper function that returns the minimum possible value for a data type.
QgsDoubleValidator is a QLineEdit Validator that combines QDoubleValidator and QRegularExpressionVali...
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
double minimumValue
The minimum cell value in the raster band.
double maximumValue
The maximum cell value in the raster band.
Feedback object tailored for raster block reading.
Qgis::DataType sourceDataType(int bandNo) const override=0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
The QgsRasterHistogram is a container for histogram of a single raster band.
double minimum
The minimum histogram value.
double maximum
The maximum histogram value.
QgsRasterHistogram::HistogramVector histogramVector
Stores the histogram for a given layer.
int binCount
Number of bins (intervals,buckets) in histogram.
Base class for processing filters like renderers, reprojector, resampler etc.
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
virtual int xSize() const
Gets raster size.
virtual Qgis::DataType sourceDataType(int bandNo) const
Returns source data type for the band specified by number, source data type may be shorter than dataT...
virtual bool hasHistogram(int bandNo, int binCount, double minimum=std::numeric_limits< double >::quiet_NaN(), double maximum=std::numeric_limits< double >::quiet_NaN(), const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, bool includeOutOfRange=false)
Returns true if histogram is available (cached, already calculated)
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
virtual int ySize() const
virtual QgsRectangle extent() const
Gets the extent of the interface.
virtual QgsRasterHistogram histogram(int bandNo, int binCount=0, double minimum=std::numeric_limits< double >::quiet_NaN(), double maximum=std::numeric_limits< double >::quiet_NaN(), const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, bool includeOutOfRange=false, QgsRasterBlockFeedback *feedback=nullptr)
Returns a band histogram.
Represents a raster layer.
int bandCount() const
Returns the number of bands in this layer.
QString bandName(int bandNoInt) const
Returns the name of a band given its number.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
A rectangle specified with double values.
QPair< QString, QString > GUI_EXPORT getSaveAsImageName(QWidget *parent, const QString &message, const QString &defaultFilename)
A helper function to get an image name from the user.