29#include <QActionGroup>
34#include <QRandomGenerator>
37#include "moc_qgsrasterhistogramwidget.cpp"
39using namespace Qt::StringLiterals;
42#include <qwt_global.h>
43#include <qwt_plot_canvas.h>
44#include <qwt_legend.h>
46#include <qwt_plot_curve.h>
47#include <qwt_plot_grid.h>
48#include <qwt_plot_marker.h>
49#include <qwt_plot_picker.h>
50#include <qwt_picker_machine.h>
51#include <qwt_plot_zoomer.h>
52#include <qwt_plot_layout.h>
53#include <qwt_plot_renderer.h>
54#include <qwt_plot_histogram.h>
55#include <qwt_scale_div.h>
69 connect( mSaveAsImageButton, &QToolButton::clicked,
this, &QgsRasterHistogramWidget::mSaveAsImageButton_clicked );
70 connect( cboHistoBand,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsRasterHistogramWidget::cboHistoBand_currentIndexChanged );
71 connect( btnHistoMin, &QToolButton::toggled,
this, &QgsRasterHistogramWidget::btnHistoMin_toggled );
72 connect( btnHistoMax, &QToolButton::toggled,
this, &QgsRasterHistogramWidget::btnHistoMax_toggled );
73 connect( btnHistoCompute, &QPushButton::clicked,
this, &QgsRasterHistogramWidget::btnHistoCompute_clicked );
77 mRendererWidget =
nullptr;
78 mRendererName = u
"singlebandgray"_s;
83 mHistoPicker =
nullptr;
84 mHistoZoomer =
nullptr;
85 mHistoMarkerMin =
nullptr;
86 mHistoMarkerMax =
nullptr;
95 mHistoShowBands = ShowAll;
101 const int myBandCountInt = mRasterLayer->bandCount();
102 for (
int myIteratorInt = 1; myIteratorInt <= myBandCountInt; ++myIteratorInt )
104 cboHistoBand->addItem( mRasterLayer->bandName( myIteratorInt ) );
105 const Qgis::DataType mySrcDataType = mRasterLayer->dataProvider()->sourceDataType( myIteratorInt );
119 connect( leHistoMin, &QLineEdit::editingFinished,
this, &QgsRasterHistogramWidget::applyHistoMin );
120 connect( leHistoMax, &QLineEdit::editingFinished,
this, &QgsRasterHistogramWidget::applyHistoMax );
124 QMenu *menu =
new QMenu(
this );
125 menu->setSeparatorsCollapsible(
false );
126 btnHistoActions->setMenu( menu );
127 QActionGroup *group =
nullptr;
128 QAction *action =
nullptr;
131 group =
new QActionGroup(
this );
132 group->setExclusive(
false );
133 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
134 action =
new QAction( tr(
"Min/Max options" ), group );
135 action->setSeparator(
true );
136 menu->addAction( action );
137 action =
new QAction( tr(
"Always show min/max markers" ), group );
138 action->setData( QVariant(
"Show markers" ) );
139 action->setCheckable(
true );
140 action->setChecked( mHistoShowMarkers );
141 menu->addAction( action );
142 action =
new QAction( tr(
"Zoom to min/max" ), group );
143 action->setData( QVariant(
"Zoom min_max" ) );
144 action->setCheckable(
true );
145 action->setChecked( mHistoZoomToMinMax );
146 menu->addAction( action );
147 action =
new QAction( tr(
"Update style to min/max" ), group );
148 action->setData( QVariant(
"Update min_max" ) );
149 action->setCheckable(
true );
150 action->setChecked( mHistoUpdateStyleToMinMax );
151 menu->addAction( action );
154 group =
new QActionGroup(
this );
155 group->setExclusive(
false );
156 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
157 action =
new QAction( tr(
"Visibility" ), group );
158 action->setSeparator(
true );
159 menu->addAction( action );
160 group =
new QActionGroup(
this );
161 group->setExclusive(
true );
162 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
163 action =
new QAction( tr(
"Show all bands" ), group );
164 action->setData( QVariant(
"Show all" ) );
165 action->setCheckable(
true );
166 action->setChecked( mHistoShowBands == ShowAll );
167 menu->addAction( action );
168 action =
new QAction( tr(
"Show RGB/Gray band(s)" ), group );
169 action->setData( QVariant(
"Show RGB" ) );
170 action->setCheckable(
true );
171 action->setChecked( mHistoShowBands == ShowRGB );
172 menu->addAction( action );
173 action =
new QAction( tr(
"Show selected band" ), group );
174 action->setData( QVariant(
"Show selected" ) );
175 action->setCheckable(
true );
176 action->setChecked( mHistoShowBands == ShowSelected );
177 menu->addAction( action );
180 group =
new QActionGroup(
this );
181 group->setExclusive(
false );
182 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
183 action =
new QAction( tr(
"Display" ), group );
184 action->setSeparator(
true );
185 menu->addAction( action );
187 action =
new QAction( QString(), group );
188 action->setData( QVariant(
"Draw lines" ) );
191 action->setText( tr(
"Draw as lines" ) );
192 action->setCheckable(
true );
193 action->setChecked( mHistoDrawLines );
197 action->setText( tr(
"Draw as lines (only int layers)" ) );
198 action->setEnabled(
false );
200 menu->addAction( action );
203 action =
new QAction( tr(
"Actions" ), group );
204 action->setSeparator(
true );
205 menu->addAction( action );
208 group =
new QActionGroup(
this );
209 group->setExclusive(
false );
210 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
211 action =
new QAction( tr(
"Reset" ), group );
212 action->setData( QVariant(
"Load reset" ) );
213 menu->addAction( action );
219 action =
new QAction( tr(
"Load min/max" ), group );
220 action->setSeparator(
true );
221 menu->addAction( action );
222 action =
new QAction( tr(
"Estimate (faster)" ), group );
223 action->setData( QVariant(
"Load estimate" ) );
224 menu->addAction( action );
225 action =
new QAction( tr(
"Actual (slower)" ), group );
226 action->setData( QVariant(
"Load actual" ) );
227 menu->addAction( action );
228 action =
new QAction( tr(
"Current extent" ), group );
229 action->setData( QVariant(
"Load extent" ) );
230 menu->addAction( action );
231 action =
new QAction( tr(
"Use stddev (1.0)" ), group );
232 action->setData( QVariant(
"Load 1 stddev" ) );
233 menu->addAction( action );
234 action =
new QAction( tr(
"Use stddev (custom)" ), group );
235 action->setData( QVariant(
"Load stddev" ) );
236 menu->addAction( action );
237 action =
new QAction( tr(
"Load for each band" ), group );
238 action->setData( QVariant(
"Load apply all" ) );
239 action->setCheckable(
true );
240 action->setChecked( mHistoLoadApplyAll );
241 menu->addAction( action );
245 action =
new QAction( tr(
"Recompute Histogram" ), group );
246 action->setData( QVariant(
"Compute histogram" ) );
247 menu->addAction( action );
254 mRendererName = name;
255 mRendererWidget = rendererWidget;
257 cboHistoBand_currentIndexChanged( -1 );
265 cboHistoBand_currentIndexChanged( -1 );
269 if ( QApplication::overrideCursor() )
270 QApplication::restoreOverrideCursor();
271 btnHistoMin->setChecked(
false );
272 btnHistoMax->setChecked(
false );
276void QgsRasterHistogramWidget::btnHistoCompute_clicked()
292static int getBinCount(
QgsRasterInterface *rasterInterface,
int bandNo,
int sampleSize )
301 xRes = yRes = std::sqrt( (
static_cast<double>( extent.width() ) * extent.height() ) / sampleSize );
306 const double srcXRes = extent.width() / rasterInterface->
xSize();
307 const double srcYRes = extent.height() / rasterInterface->
ySize();
308 if ( xRes < srcXRes )
310 if ( yRes < srcYRes )
314 const int histogramWidth =
static_cast<int>( extent.width() / xRes );
315 const int histogramHeight =
static_cast<int>( extent.height() / yRes );
317 int binCount =
static_cast<int>( std::min(
static_cast<qint64
>( 1000 ),
static_cast<qint64
>( histogramWidth ) * histogramHeight ) );
321 binCount =
static_cast<int>( std::min(
static_cast<qint64
>( binCount ),
static_cast<qint64
>( std::ceil( statsMax - statsMin + 1 ) ) ) );
331 const int myBandCountInt = mRasterLayer->bandCount();
334 if ( !forceComputeFlag )
336 for (
int myIteratorInt = 1; myIteratorInt <= myBandCountInt; ++myIteratorInt )
339 const int binCount = getBinCount( mRasterLayer->dataProvider(), myIteratorInt, sampleSize );
340 if ( !mRasterLayer->dataProvider()->hasHistogram( myIteratorInt, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(),
QgsRectangle(), sampleSize ) )
342 QgsDebugMsgLevel( u
"band %1 does not have cached histo"_s.arg( myIteratorInt ), 2 );
349 stackedWidget2->setCurrentIndex( 1 );
353 QApplication::setOverrideCursor( Qt::WaitCursor );
355 for (
int myIteratorInt = 1; myIteratorInt <= myBandCountInt; ++myIteratorInt )
358 const int binCount = getBinCount( mRasterLayer->dataProvider(), myIteratorInt, sampleSize );
359 mRasterLayer->dataProvider()->histogram( myIteratorInt, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(),
QgsRectangle(), sampleSize,
false, feedback.get() );
363 stackedWidget2->setCurrentIndex( 0 );
364 QApplication::restoreOverrideCursor();
381 const int myBandCountInt = mRasterLayer->bandCount();
387 stackedWidget2->setCurrentIndex( 2 );
392 mpPlot->detachItems();
395 mpPlot->setAutoDelete(
true );
396 mpPlot->setTitle( QObject::tr(
"Raster Histogram" ) );
397 mpPlot->insertLegend(
new QwtLegend(), QwtPlot::BottomLegend );
399 mpPlot->setAxisTitle( QwtPlot::xBottom, QObject::tr(
"Pixel Value" ) );
400 mpPlot->setAxisTitle( QwtPlot::yLeft, QObject::tr(
"Frequency" ) );
401 mpPlot->setAxisAutoScale( QwtPlot::yLeft );
405 QwtPlotGrid *myGrid =
new QwtPlotGrid();
406 myGrid->attach( mpPlot );
409 mHistoColors.clear();
410 mHistoColors << Qt::black;
411 QVector<QColor> myColors;
412 myColors << Qt::red << Qt::green << Qt::blue << Qt::magenta << Qt::darkYellow << Qt::cyan;
415 QRandomGenerator colorGenerator( myBandCountInt * 100 );
416 while ( myColors.size() <= myBandCountInt )
418 myColors << QColor( colorGenerator.bounded( 1, 256 ), colorGenerator.bounded( 1, 256 ), colorGenerator.bounded( 1, 256 ) );
423 QList<int> mySelectedBands = rendererSelectedBands();
424 if ( mRendererName ==
"singlebandgray"_L1 )
426 const int myGrayBand = mySelectedBands[0];
427 for (
int i = 1; i <= myBandCountInt; i++ )
429 if ( i == myGrayBand )
431 mHistoColors << Qt::darkGray;
432 cboHistoBand->setItemData( i - 1, QColor( Qt::darkGray ), Qt::ForegroundRole );
436 if ( !myColors.isEmpty() )
438 mHistoColors << myColors.first();
439 myColors.pop_front();
443 mHistoColors << Qt::black;
445 cboHistoBand->setItemData( i - 1, QColor( Qt::black ), Qt::ForegroundRole );
450 else if ( mRendererName ==
"multibandcolor"_L1 )
452 const int myRedBand = mySelectedBands[0];
453 const int myGreenBand = mySelectedBands[1];
454 const int myBlueBand = mySelectedBands[2];
457 myColors.remove( 0, 3 );
458 for (
int i = 1; i <= myBandCountInt; i++ )
461 if ( i == myRedBand )
463 else if ( i == myGreenBand )
465 else if ( i == myBlueBand )
469 if ( !myColors.isEmpty() )
471 myColor = myColors.first();
472 myColors.pop_front();
478 cboHistoBand->setItemData( i - 1, QColor( Qt::black ), Qt::ForegroundRole );
480 if ( i == myRedBand || i == myGreenBand || i == myBlueBand )
482 cboHistoBand->setItemData( i - 1, myColor, Qt::ForegroundRole );
484 mHistoColors << myColor;
489 mHistoColors << myColors;
504 bool myFirstIteration =
true;
506 mySelectedBands = histoSelectedBands();
507 double myBinXStep = 1;
510 for (
int bandNumber = 1; bandNumber <= myBandCountInt; ++bandNumber )
513 if ( mHistoShowBands != ShowAll )
515 if ( !mySelectedBands.contains( bandNumber ) )
524 const int binCount = getBinCount( mRasterLayer->dataProvider(), bandNumber, sampleSize );
526 = mRasterLayer->dataProvider()->histogram( bandNumber, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(),
QgsRectangle(), sampleSize,
false, feedback.get() );
530 const Qgis::DataType mySrcDataType = mRasterLayer->dataProvider()->sourceDataType( bandNumber );
531 bool myDrawLines =
true;
532 if ( !mHistoDrawLines
538 QwtPlotCurve *mypCurve =
nullptr;
541 mypCurve =
new QwtPlotCurve( tr(
"Band %1" ).arg( bandNumber ) );
543 mypCurve->setRenderHint( QwtPlotItem::RenderAntialiased );
544 mypCurve->setPen( QPen( mHistoColors.at( bandNumber ) ) );
547 QwtPlotHistogram *mypHisto =
nullptr;
550 mypHisto =
new QwtPlotHistogram( tr(
"Band %1" ).arg( bandNumber ) );
551 mypHisto->setRenderHint( QwtPlotItem::RenderAntialiased );
553 mypHisto->setPen( QPen( Qt::lightGray ) );
555 mypHisto->setBrush( QBrush( mHistoColors.at( bandNumber ) ) );
558 QVector<QPointF> data;
559 QVector<QwtIntervalSample> dataHisto;
563 myBinX = myHistogram.
minimum + myBinXStep / 2.0;
565 for (
int myBin = 0; myBin < myHistogram.
binCount; myBin++ )
570 data << QPointF( myBinX, myBinValue );
574 dataHisto << QwtIntervalSample( myBinValue, myBinX - myBinXStep / 2.0, myBinX + myBinXStep / 2.0 );
576 myBinX += myBinXStep;
581 mypCurve->setSamples( data );
582 mypCurve->attach( mpPlot );
586 mypHisto->setSamples( dataHisto );
587 mypHisto->attach( mpPlot );
590 if ( myFirstIteration || mHistoMin > myHistogram.
minimum )
592 mHistoMin = myHistogram.
minimum;
594 if ( myFirstIteration || mHistoMax < myHistogram.
maximum )
596 mHistoMax = myHistogram.
maximum;
598 QgsDebugMsgLevel( u
"computed histo min = %1 max = %2"_s.arg( mHistoMin ).arg( mHistoMax ), 2 );
599 myFirstIteration =
false;
602 if ( mHistoMin < mHistoMax )
608 mpPlot->setAxisScale( QwtPlot::xBottom, mHistoMin - myBinXStep / 2, mHistoMax + myBinXStep / 2 );
609 mpPlot->setEnabled(
true );
614 mHistoMarkerMin =
new QwtPlotMarker();
615 mHistoMarkerMin->attach( mpPlot );
616 mHistoMarkerMax =
new QwtPlotMarker();
617 mHistoMarkerMax->attach( mpPlot );
618 updateHistoMarkers();
623 mHistoPicker =
new QwtPlotPicker( mpPlot->canvas() );
625 mHistoPicker->setTrackerMode( QwtPicker::AlwaysOff );
626 mHistoPicker->setRubberBand( QwtPicker::VLineRubberBand );
627 mHistoPicker->setStateMachine(
new QwtPickerDragPointMachine );
628 connect( mHistoPicker,
static_cast<void ( QwtPlotPicker::* )(
const QPointF & )
>( &QwtPlotPicker::selected ),
this, &QgsRasterHistogramWidget::histoPickerSelected );
630 mHistoPicker->setEnabled(
false );
635 mHistoZoomer =
new QwtPlotZoomer( mpPlot->canvas() );
636 mHistoZoomer->setStateMachine(
new QwtPickerDragRectMachine );
637 mHistoZoomer->setTrackerMode( QwtPicker::AlwaysOff );
639 mHistoZoomer->setEnabled(
true );
643 mpPlot->setDisabled(
true );
645 mHistoPicker->setEnabled(
false );
647 mHistoZoomer->setEnabled(
false );
650 stackedWidget2->setCurrentIndex( 0 );
654 QApplication::restoreOverrideCursor();
657void QgsRasterHistogramWidget::mSaveAsImageButton_clicked()
663 const QFileInfo myInfo( myFileNameAndFilter.first );
664 if ( !myInfo.baseName().isEmpty() )
673 const QFileInfo myInfo( filename );
674 const QDir myDir( myInfo.dir() );
675 if ( !myDir.exists() )
677 QgsDebugError( u
"Error, directory %1 non-existent (theFilename = %2)"_s.arg( myDir.absolutePath(), filename ) );
682 QPixmap myPixmap( width, height );
683 const QRect myQRect( 5, 5, width - 10, height - 10 );
684 myPixmap.fill( Qt::white );
686 QwtPlotRenderer myRenderer;
687 myRenderer.setDiscardFlags( QwtPlotRenderer::DiscardBackground | QwtPlotRenderer::DiscardCanvasBackground );
688 myRenderer.setLayoutFlags( QwtPlotRenderer::FrameWithScales );
691 myPainter.begin( &myPixmap );
692 myRenderer.render( mpPlot, &myPainter, myQRect );
696 myPixmap.save( filename,
nullptr, quality );
704 cboHistoBand->setCurrentIndex( bandNo - 1 );
707void QgsRasterHistogramWidget::cboHistoBand_currentIndexChanged(
int index )
709 if ( mHistoShowBands == ShowSelected )
713 index = cboHistoBand->currentIndex();
716 mHistoPicker->setEnabled(
false );
717 mHistoPicker->setRubberBandPen( QPen( mHistoColors.at( index + 1 ) ) );
720 mHistoZoomer->setEnabled(
true );
721 btnHistoMin->setEnabled(
true );
722 btnHistoMax->setEnabled(
true );
724 const QPair<QString, QString> myMinMax = rendererMinMax( index + 1 );
725 leHistoMin->setText( myMinMax.first );
726 leHistoMax->setText( myMinMax.second );
732void QgsRasterHistogramWidget::histoActionTriggered( QAction *action )
736 histoAction( action->data().toString(), action->isChecked() );
741 if ( actionName.isEmpty() )
745 QgsDebugMsgLevel( u
"band = %1 action = %2"_s.arg( cboHistoBand->currentIndex() + 1 ).arg( actionName ), 2 );
748 if ( actionName ==
"Show markers"_L1 )
750 mHistoShowMarkers = actionFlag;
752 updateHistoMarkers();
755 else if ( actionName ==
"Zoom min_max"_L1 )
757 mHistoZoomToMinMax = actionFlag;
761 else if ( actionName ==
"Update min_max"_L1 )
763 mHistoUpdateStyleToMinMax = actionFlag;
767 else if ( actionName ==
"Show all"_L1 )
769 mHistoShowBands = ShowAll;
774 else if ( actionName ==
"Show selected"_L1 )
776 mHistoShowBands = ShowSelected;
781 else if ( actionName ==
"Show RGB"_L1 )
783 mHistoShowBands = ShowRGB;
788 else if ( actionName ==
"Draw lines"_L1 )
790 mHistoDrawLines = actionFlag;
792 btnHistoCompute_clicked();
796 else if ( actionName ==
"Load apply all" )
798 mHistoLoadApplyAll = actionFlag;
799 settings.setValue(
"/Raster/histogram/loadApplyAll", mHistoLoadApplyAll );
805 else if ( actionName.left( 5 ) ==
"Load "_L1 && mRendererWidget )
807 QVector<int> myBands;
811 double minMaxValues[2];
814 if ( mHistoLoadApplyAll )
816 int myBandCountInt = mRasterLayer->bandCount();
817 for (
int i = 1; i <= myBandCountInt; i++ )
819 if ( i != cboHistoBand->currentIndex() + 1 )
826 myBands << cboHistoBand->currentIndex() + 1;
830 double myStdDev = 1.0;
831 if ( actionName ==
"Load stddev" )
833 myStdDev = mRendererWidget->stdDev().toDouble();
838 leHistoMin->blockSignals(
true );
839 leHistoMax->blockSignals(
true );
842 const auto constMyBands = myBands;
843 for (
const int bandNo : constMyBands )
847 if ( actionName ==
"Load actual" )
849 ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::Actual,
850 bandNo, minMaxValues );
852 else if ( actionName ==
"Load estimate" )
854 ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::Estimate,
855 bandNo, minMaxValues );
857 else if ( actionName ==
"Load extent" )
859 ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::CurrentExtent,
860 bandNo, minMaxValues );
862 else if ( actionName ==
"Load 1 stddev" ||
863 actionName ==
"Load stddev" )
865 ok = mRendererWidget->bandMinMaxFromStdDev( myStdDev, bandNo, minMaxValues );
870 cboHistoBand->setCurrentIndex( bandNo - 1 );
871 if ( !ok || actionName ==
"Load reset"_L1 )
879 (
Qgis::DataType ) mRasterLayer->dataProvider()->dataType( bandNo ) );
881 (
Qgis::DataType ) mRasterLayer->dataProvider()->dataType( bandNo ) );
885 leHistoMin->setText( QString::number( minMaxValues[0] ) );
886 leHistoMax->setText( QString::number( minMaxValues[1] ) );
893 leHistoMin->blockSignals(
false );
894 leHistoMax->blockSignals(
false );
895 updateHistoMarkers();
897 else if ( actionName ==
"Compute histogram"_L1 )
899 btnHistoCompute_clicked();
908void QgsRasterHistogramWidget::applyHistoMin()
910 if ( !mRendererWidget )
913 const int bandNo = cboHistoBand->currentIndex() + 1;
914 const QList<int> selectedBands = rendererSelectedBands();
916 for (
int i = 0; i <= selectedBands.size(); i++ )
920 min = leHistoMin->text();
921 if ( mHistoUpdateStyleToMinMax && mRendererWidget->
min( i ) != min )
923 mRendererWidget->
setMin( min, i );
928 if ( mRendererWidget->minMaxWidget() )
930 mRendererWidget->minMaxWidget()->userHasSetManualMinMaxValues();
936 updateHistoMarkers();
938 if ( !min.isEmpty() && mHistoZoomToMinMax && mHistoZoomer )
940 QRectF rect = mHistoZoomer->zoomRect();
941 rect.setLeft( min.toDouble() );
942 mHistoZoomer->zoom( rect );
947void QgsRasterHistogramWidget::applyHistoMax()
949 if ( !mRendererWidget )
952 const int bandNo = cboHistoBand->currentIndex() + 1;
953 const QList<int> mySelectedBands = rendererSelectedBands();
955 for (
int i = 0; i <= mySelectedBands.size(); i++ )
957 if ( bandNo == mRendererWidget->selectedBand( i ) )
959 max = leHistoMax->text();
960 if ( mHistoUpdateStyleToMinMax && mRendererWidget->max( i ) != max )
962 mRendererWidget->setMax( max, i );
967 if ( mRendererWidget->minMaxWidget() )
969 mRendererWidget->minMaxWidget()->userHasSetManualMinMaxValues();
975 updateHistoMarkers();
977 if ( !max.isEmpty() && mHistoZoomToMinMax && mHistoZoomer )
979 QRectF rect = mHistoZoomer->zoomRect();
980 rect.setRight( max.toDouble() );
981 mHistoZoomer->zoom( rect );
986void QgsRasterHistogramWidget::btnHistoMin_toggled()
988 if ( mpPlot && mHistoPicker )
990 if ( QApplication::overrideCursor() )
991 QApplication::restoreOverrideCursor();
992 if ( btnHistoMin->isChecked() )
994 btnHistoMax->setChecked(
false );
995 QApplication::setOverrideCursor( Qt::PointingHandCursor );
998 mHistoZoomer->setEnabled( !btnHistoMin->isChecked() );
999 mHistoPicker->setEnabled( btnHistoMin->isChecked() );
1001 updateHistoMarkers();
1004void QgsRasterHistogramWidget::btnHistoMax_toggled()
1006 if ( mpPlot && mHistoPicker )
1008 if ( QApplication::overrideCursor() )
1009 QApplication::restoreOverrideCursor();
1010 if ( btnHistoMax->isChecked() )
1012 btnHistoMin->setChecked(
false );
1013 QApplication::setOverrideCursor( Qt::PointingHandCursor );
1016 mHistoZoomer->setEnabled( !btnHistoMax->isChecked() );
1017 mHistoPicker->setEnabled( btnHistoMax->isChecked() );
1019 updateHistoMarkers();
1029 QList<double> minorTicks = scale->ticks( QwtScaleDiv::MinorTick );
1030 QList<double> majorTicks = scale->ticks( QwtScaleDiv::MajorTick );
1031 const double diff = ( minorTicks[1] - minorTicks[0] ) / div;
1032 double min = majorTicks[0] - diff;
1034 min -= ( majorTicks[1] - majorTicks[0] );
1035 const double max = scale->upperBound();
1036 double closest = target;
1037 double current = min;
1039 while ( current < max )
1042 if ( current > target )
1044 closest = ( std::fabs( target - current + diff ) < std::fabs( target - current ) ) ? current - diff : current;
1050 return QLocale().toString( closest );
1053void QgsRasterHistogramWidget::histoPickerSelected( QPointF pos )
1055 if ( btnHistoMin->isChecked() || btnHistoMax->isChecked() )
1057 const QwtScaleDiv *scale = &mpPlot->axisScaleDiv( QwtPlot::xBottom );
1059 if ( btnHistoMin->isChecked() )
1063 btnHistoMin->setChecked(
false );
1069 btnHistoMax->setChecked(
false );
1072 if ( QApplication::overrideCursor() )
1073 QApplication::restoreOverrideCursor();
1076void QgsRasterHistogramWidget::histoPickerSelectedQwt5(
QwtDoublePoint pos )
1078 histoPickerSelected( QPointF( pos.x(), pos.y() ) );
1081void QgsRasterHistogramWidget::updateHistoMarkers()
1084 if ( leHistoMin->signalsBlocked() )
1087 if ( !mpPlot || !mHistoMarkerMin || !mHistoMarkerMax )
1090 const int bandNo = cboHistoBand->currentIndex() + 1;
1091 const QList<int> mySelectedBands = histoSelectedBands();
1093 if ( ( !mHistoShowMarkers && !btnHistoMin->isChecked() && !btnHistoMax->isChecked() ) || ( !mySelectedBands.isEmpty() && !mySelectedBands.contains( bandNo ) ) )
1095 mHistoMarkerMin->hide();
1096 mHistoMarkerMax->hide();
1101 double minVal = mHistoMin;
1102 double maxVal = mHistoMax;
1103 const QString minStr = leHistoMin->text();
1104 const QString maxStr = leHistoMax->text();
1105 if ( !minStr.isEmpty() )
1106 minVal = minStr.toDouble();
1107 if ( !maxStr.isEmpty() )
1108 maxVal = maxStr.toDouble();
1110 QPen linePen = QPen( mHistoColors.at( bandNo ) );
1111 linePen.setStyle( Qt::DashLine );
1112 mHistoMarkerMin->setLineStyle( QwtPlotMarker::VLine );
1113 mHistoMarkerMin->setLinePen( linePen );
1114 mHistoMarkerMin->setXValue( minVal );
1115 mHistoMarkerMin->show();
1116 mHistoMarkerMax->setLineStyle( QwtPlotMarker::VLine );
1117 mHistoMarkerMax->setLinePen( linePen );
1118 mHistoMarkerMax->setXValue( maxVal );
1119 mHistoMarkerMax->show();
1125QList<int> QgsRasterHistogramWidget::histoSelectedBands()
1127 QList<int> mySelectedBands;
1129 if ( mHistoShowBands != ShowAll )
1131 if ( mHistoShowBands == ShowSelected )
1133 mySelectedBands << cboHistoBand->currentIndex() + 1;
1135 else if ( mHistoShowBands == ShowRGB )
1137 mySelectedBands = rendererSelectedBands();
1141 return mySelectedBands;
1144QList<int> QgsRasterHistogramWidget::rendererSelectedBands()
1146 QList<int> mySelectedBands;
1148 if ( !mRendererWidget )
1150 mySelectedBands << -1 << -1 << -1;
1151 return mySelectedBands;
1154 if ( mRendererName ==
"singlebandgray"_L1 || mRendererName ==
"singlebandpseudocolor"_L1 )
1156 mySelectedBands << mRendererWidget->selectedBand();
1158 else if ( mRendererName ==
"multibandcolor"_L1 )
1160 for (
int i = 0; i <= 2; i++ )
1162 mySelectedBands << mRendererWidget->selectedBand( i );
1166 return mySelectedBands;
1169QPair<QString, QString> QgsRasterHistogramWidget::rendererMinMax(
int bandNo )
1171 QPair<QString, QString> myMinMax;
1173 if ( !mRendererWidget )
1176 if ( mRendererName ==
"singlebandgray"_L1 || mRendererName ==
"singlebandpseudocolor"_L1 )
1178 if ( bandNo == mRendererWidget->selectedBand() )
1180 myMinMax.first = mRendererWidget->min();
1181 myMinMax.second = mRendererWidget->max();
1184 else if ( mRendererName ==
"multibandcolor"_L1 )
1186 for (
int i = 0; i <= 2; i++ )
1188 if ( bandNo == mRendererWidget->selectedBand( i ) )
1190 myMinMax.first = mRendererWidget->min( i );
1191 myMinMax.second = mRendererWidget->max( i );
1207 if ( myMinMax.first.isEmpty() )
1208 myMinMax.first = QLocale().toString( mHistoMin );
1209 if ( myMinMax.second.isEmpty() )
1210 myMinMax.second = QLocale().toString( mHistoMax );
1212 QgsDebugMsgLevel( u
"bandNo %1 got min/max [%2] [%3]"_s.arg( bandNo ).arg( myMinMax.first, myMinMax.second ), 2 );
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
DataType
Raster data types.
@ Int16
Sixteen bit signed integer (qint16).
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30).
@ 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.
@ StretchToMinimumMaximum
Linear histogram.
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
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.
A custom validator which allows entry of doubles in a locale-tolerant way.
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.
A container for a 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.
virtual Qgis::RasterInterfaceCapabilities capabilities() const
Returns the capabilities supported by the interface.
virtual int xSize() const
Gets raster size.
Q_DECL_DEPRECATED QgsRasterBandStats bandStatistics(int bandNo, int stats, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
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 int ySize() const
virtual QgsRectangle extent() const
Gets the extent of the interface.
Represents a raster layer.
A rectangle specified with double values.
static const QgsSettingsEntryBool * settingsRasterHistogramDrawLines
Settings entry raster histogram draw lines.
static const QgsSettingsEntryBool * settingsRasterHistogramZoomToMinMax
Settings entry raster histogram zoom to min/max.
static const QgsSettingsEntryBool * settingsRasterHistogramUpdateStyleToMinMax
Settings entry raster histogram update style to min/max.
static const QgsSettingsEntryBool * settingsRasterHistogramShowMarkers
Settings entry raster histogram show markers.
Stores settings for use within QGIS.
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.
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)