28#include <QActionGroup>
33#include <QRandomGenerator>
35#include "moc_qgsrasterhistogramwidget.cpp"
38#include <qwt_global.h>
39#include <qwt_plot_canvas.h>
40#include <qwt_legend.h>
42#include <qwt_plot_curve.h>
43#include <qwt_plot_grid.h>
44#include <qwt_plot_marker.h>
45#include <qwt_plot_picker.h>
46#include <qwt_picker_machine.h>
47#include <qwt_plot_zoomer.h>
48#include <qwt_plot_layout.h>
49#include <qwt_plot_renderer.h>
50#include <qwt_plot_histogram.h>
51#include <qwt_scale_div.h>
65 connect( mSaveAsImageButton, &QToolButton::clicked,
this, &QgsRasterHistogramWidget::mSaveAsImageButton_clicked );
66 connect( cboHistoBand,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsRasterHistogramWidget::cboHistoBand_currentIndexChanged );
67 connect( btnHistoMin, &QToolButton::toggled,
this, &QgsRasterHistogramWidget::btnHistoMin_toggled );
68 connect( btnHistoMax, &QToolButton::toggled,
this, &QgsRasterHistogramWidget::btnHistoMax_toggled );
69 connect( btnHistoCompute, &QPushButton::clicked,
this, &QgsRasterHistogramWidget::btnHistoCompute_clicked );
73 mRendererWidget =
nullptr;
74 mRendererName = QStringLiteral(
"singlebandgray" );
79 mHistoPicker =
nullptr;
80 mHistoZoomer =
nullptr;
81 mHistoMarkerMin =
nullptr;
82 mHistoMarkerMax =
nullptr;
85 mHistoShowMarkers = settings.
value( QStringLiteral(
"Raster/histogram/showMarkers" ),
false ).toBool();
87 mHistoZoomToMinMax = settings.
value( QStringLiteral(
"Raster/histogram/zoomToMinMax" ),
false ).toBool();
88 mHistoUpdateStyleToMinMax = settings.
value( QStringLiteral(
"Raster/histogram/updateStyleToMinMax" ),
true ).toBool();
89 mHistoDrawLines = settings.
value( QStringLiteral(
"Raster/histogram/drawLines" ),
true ).toBool();
91 mHistoShowBands = ShowAll;
97 const int myBandCountInt = mRasterLayer->bandCount();
98 for (
int myIteratorInt = 1;
99 myIteratorInt <= myBandCountInt;
102 cboHistoBand->addItem( mRasterLayer->bandName( myIteratorInt ) );
103 const Qgis::DataType mySrcDataType = mRasterLayer->dataProvider()->sourceDataType( myIteratorInt );
112 connect( leHistoMin, &QLineEdit::editingFinished,
this, &QgsRasterHistogramWidget::applyHistoMin );
113 connect( leHistoMax, &QLineEdit::editingFinished,
this, &QgsRasterHistogramWidget::applyHistoMax );
117 QMenu *menu =
new QMenu(
this );
118 menu->setSeparatorsCollapsible(
false );
119 btnHistoActions->setMenu( menu );
120 QActionGroup *group =
nullptr;
121 QAction *action =
nullptr;
124 group =
new QActionGroup(
this );
125 group->setExclusive(
false );
126 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
127 action =
new QAction( tr(
"Min/Max options" ), group );
128 action->setSeparator(
true );
129 menu->addAction( action );
130 action =
new QAction( tr(
"Always show min/max markers" ), group );
131 action->setData( QVariant(
"Show markers" ) );
132 action->setCheckable(
true );
133 action->setChecked( mHistoShowMarkers );
134 menu->addAction( action );
135 action =
new QAction( tr(
"Zoom to min/max" ), group );
136 action->setData( QVariant(
"Zoom min_max" ) );
137 action->setCheckable(
true );
138 action->setChecked( mHistoZoomToMinMax );
139 menu->addAction( action );
140 action =
new QAction( tr(
"Update style to min/max" ), group );
141 action->setData( QVariant(
"Update min_max" ) );
142 action->setCheckable(
true );
143 action->setChecked( mHistoUpdateStyleToMinMax );
144 menu->addAction( action );
147 group =
new QActionGroup(
this );
148 group->setExclusive(
false );
149 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
150 action =
new QAction( tr(
"Visibility" ), group );
151 action->setSeparator(
true );
152 menu->addAction( action );
153 group =
new QActionGroup(
this );
154 group->setExclusive(
true );
155 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
156 action =
new QAction( tr(
"Show all bands" ), group );
157 action->setData( QVariant(
"Show all" ) );
158 action->setCheckable(
true );
159 action->setChecked( mHistoShowBands == ShowAll );
160 menu->addAction( action );
161 action =
new QAction( tr(
"Show RGB/Gray band(s)" ), group );
162 action->setData( QVariant(
"Show RGB" ) );
163 action->setCheckable(
true );
164 action->setChecked( mHistoShowBands == ShowRGB );
165 menu->addAction( action );
166 action =
new QAction( tr(
"Show selected band" ), group );
167 action->setData( QVariant(
"Show selected" ) );
168 action->setCheckable(
true );
169 action->setChecked( mHistoShowBands == ShowSelected );
170 menu->addAction( action );
173 group =
new QActionGroup(
this );
174 group->setExclusive(
false );
175 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
176 action =
new QAction( tr(
"Display" ), group );
177 action->setSeparator(
true );
178 menu->addAction( action );
180 action =
new QAction( QString(), group );
181 action->setData( QVariant(
"Draw lines" ) );
184 action->setText( tr(
"Draw as lines" ) );
185 action->setCheckable(
true );
186 action->setChecked( mHistoDrawLines );
190 action->setText( tr(
"Draw as lines (only int layers)" ) );
191 action->setEnabled(
false );
193 menu->addAction( action );
196 action =
new QAction( tr(
"Actions" ), group );
197 action->setSeparator(
true );
198 menu->addAction( action );
201 group =
new QActionGroup(
this );
202 group->setExclusive(
false );
203 connect( group, &QActionGroup::triggered,
this, &QgsRasterHistogramWidget::histoActionTriggered );
204 action =
new QAction( tr(
"Reset" ), group );
205 action->setData( QVariant(
"Load reset" ) );
206 menu->addAction( action );
212 action =
new QAction( tr(
"Load min/max" ), group );
213 action->setSeparator(
true );
214 menu->addAction( action );
215 action =
new QAction( tr(
"Estimate (faster)" ), group );
216 action->setData( QVariant(
"Load estimate" ) );
217 menu->addAction( action );
218 action =
new QAction( tr(
"Actual (slower)" ), group );
219 action->setData( QVariant(
"Load actual" ) );
220 menu->addAction( action );
221 action =
new QAction( tr(
"Current extent" ), group );
222 action->setData( QVariant(
"Load extent" ) );
223 menu->addAction( action );
224 action =
new QAction( tr(
"Use stddev (1.0)" ), group );
225 action->setData( QVariant(
"Load 1 stddev" ) );
226 menu->addAction( action );
227 action =
new QAction( tr(
"Use stddev (custom)" ), group );
228 action->setData( QVariant(
"Load stddev" ) );
229 menu->addAction( action );
230 action =
new QAction( tr(
"Load for each band" ), group );
231 action->setData( QVariant(
"Load apply all" ) );
232 action->setCheckable(
true );
233 action->setChecked( mHistoLoadApplyAll );
234 menu->addAction( action );
238 action =
new QAction( tr(
"Recompute Histogram" ), group );
239 action->setData( QVariant(
"Compute histogram" ) );
240 menu->addAction( action );
247 mRendererName = name;
248 mRendererWidget = rendererWidget;
250 cboHistoBand_currentIndexChanged( -1 );
258 cboHistoBand_currentIndexChanged( -1 );
262 if ( QApplication::overrideCursor() )
263 QApplication::restoreOverrideCursor();
264 btnHistoMin->setChecked(
false );
265 btnHistoMax->setChecked(
false );
269void QgsRasterHistogramWidget::btnHistoCompute_clicked()
285static int getBinCount(
QgsRasterInterface *rasterInterface,
int bandNo,
int sampleSize )
294 xRes = yRes = std::sqrt( (
static_cast<double>( extent.width() ) * extent.height() ) / sampleSize );
299 const double srcXRes = extent.width() / rasterInterface->
xSize();
300 const double srcYRes = extent.height() / rasterInterface->
ySize();
301 if ( xRes < srcXRes )
303 if ( yRes < srcYRes )
307 const int histogramWidth =
static_cast<int>( extent.width() / xRes );
308 const int histogramHeight =
static_cast<int>( extent.height() / yRes );
310 int binCount =
static_cast<int>( std::min(
static_cast<qint64
>( 1000 ),
static_cast<qint64
>( histogramWidth ) * histogramHeight ) );
314 binCount =
static_cast<int>( std::min(
static_cast<qint64
>( binCount ),
static_cast<qint64
>( std::ceil( statsMax - statsMin + 1 ) ) ) );
324 const int myBandCountInt = mRasterLayer->bandCount();
327 if ( !forceComputeFlag )
329 for (
int myIteratorInt = 1;
330 myIteratorInt <= myBandCountInt;
334 const int binCount = getBinCount( mRasterLayer->dataProvider(), myIteratorInt, sampleSize );
335 if ( !mRasterLayer->dataProvider()->hasHistogram( myIteratorInt, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(),
QgsRectangle(), sampleSize ) )
337 QgsDebugMsgLevel( QStringLiteral(
"band %1 does not have cached histo" ).arg( myIteratorInt ), 2 );
344 stackedWidget2->setCurrentIndex( 1 );
348 QApplication::setOverrideCursor( Qt::WaitCursor );
350 for (
int myIteratorInt = 1;
351 myIteratorInt <= myBandCountInt;
355 const int binCount = getBinCount( mRasterLayer->dataProvider(), myIteratorInt, sampleSize );
356 mRasterLayer->dataProvider()->histogram( myIteratorInt, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(),
QgsRectangle(), sampleSize,
false, feedback.get() );
360 stackedWidget2->setCurrentIndex( 0 );
361 QApplication::restoreOverrideCursor();
378 const int myBandCountInt = mRasterLayer->bandCount();
383 QgsDebugMsgLevel( QStringLiteral(
"raster does not have cached histogram" ), 2 );
384 stackedWidget2->setCurrentIndex( 2 );
389 mpPlot->detachItems();
392 mpPlot->setAutoDelete(
true );
393 mpPlot->setTitle( QObject::tr(
"Raster Histogram" ) );
394 mpPlot->insertLegend(
new QwtLegend(), QwtPlot::BottomLegend );
396 mpPlot->setAxisTitle( QwtPlot::xBottom, QObject::tr(
"Pixel Value" ) );
397 mpPlot->setAxisTitle( QwtPlot::yLeft, QObject::tr(
"Frequency" ) );
398 mpPlot->setAxisAutoScale( QwtPlot::yLeft );
402 QwtPlotGrid *myGrid =
new QwtPlotGrid();
403 myGrid->attach( mpPlot );
406 mHistoColors.clear();
407 mHistoColors << Qt::black;
408 QVector<QColor> myColors;
409 myColors << Qt::red << Qt::green << Qt::blue << Qt::magenta << Qt::darkYellow << Qt::cyan;
412 QRandomGenerator colorGenerator( myBandCountInt * 100 );
413 while ( myColors.size() <= myBandCountInt )
415 myColors << QColor( colorGenerator.bounded( 1, 256 ), colorGenerator.bounded( 1, 256 ), colorGenerator.bounded( 1, 256 ) );
420 QList<int> mySelectedBands = rendererSelectedBands();
421 if ( mRendererName == QLatin1String(
"singlebandgray" ) )
423 const int myGrayBand = mySelectedBands[0];
424 for (
int i = 1; i <= myBandCountInt; i++ )
426 if ( i == myGrayBand )
428 mHistoColors << Qt::darkGray;
429 cboHistoBand->setItemData( i - 1, QColor( Qt::darkGray ), Qt::ForegroundRole );
433 if ( !myColors.isEmpty() )
435 mHistoColors << myColors.first();
436 myColors.pop_front();
440 mHistoColors << Qt::black;
442 cboHistoBand->setItemData( i - 1, QColor( Qt::black ), Qt::ForegroundRole );
447 else if ( mRendererName == QLatin1String(
"multibandcolor" ) )
449 const int myRedBand = mySelectedBands[0];
450 const int myGreenBand = mySelectedBands[1];
451 const int myBlueBand = mySelectedBands[2];
454 myColors.remove( 0, 3 );
455 for (
int i = 1; i <= myBandCountInt; i++ )
458 if ( i == myRedBand )
460 else if ( i == myGreenBand )
462 else if ( i == myBlueBand )
466 if ( !myColors.isEmpty() )
468 myColor = myColors.first();
469 myColors.pop_front();
475 cboHistoBand->setItemData( i - 1, QColor( Qt::black ), Qt::ForegroundRole );
477 if ( i == myRedBand || i == myGreenBand || i == myBlueBand )
479 cboHistoBand->setItemData( i - 1, myColor, Qt::ForegroundRole );
481 mHistoColors << myColor;
486 mHistoColors << myColors;
501 bool myFirstIteration =
true;
503 mySelectedBands = histoSelectedBands();
504 double myBinXStep = 1;
507 for (
int bandNumber = 1;
508 bandNumber <= myBandCountInt;
512 if ( mHistoShowBands != ShowAll )
514 if ( !mySelectedBands.contains( bandNumber ) )
523 const int binCount = getBinCount( mRasterLayer->dataProvider(), bandNumber, sampleSize );
524 const QgsRasterHistogram myHistogram = mRasterLayer->dataProvider()->histogram( bandNumber, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(),
QgsRectangle(), sampleSize,
false, feedback.get() );
526 QgsDebugMsgLevel( QStringLiteral(
"got raster histo for band %1 : min=%2 max=%3 count=%4" ).arg( bandNumber ).arg( myHistogram.
minimum ).arg( myHistogram.
maximum ).arg( myHistogram.
binCount ), 2 );
528 const Qgis::DataType mySrcDataType = mRasterLayer->dataProvider()->sourceDataType( bandNumber );
529 bool myDrawLines =
true;
535 QwtPlotCurve *mypCurve =
nullptr;
538 mypCurve =
new QwtPlotCurve( tr(
"Band %1" ).arg( bandNumber ) );
540 mypCurve->setRenderHint( QwtPlotItem::RenderAntialiased );
541 mypCurve->setPen( QPen( mHistoColors.at( bandNumber ) ) );
544 QwtPlotHistogram *mypHisto =
nullptr;
547 mypHisto =
new QwtPlotHistogram( tr(
"Band %1" ).arg( bandNumber ) );
548 mypHisto->setRenderHint( QwtPlotItem::RenderAntialiased );
550 mypHisto->setPen( QPen( Qt::lightGray ) );
552 mypHisto->setBrush( QBrush( mHistoColors.at( bandNumber ) ) );
555 QVector<QPointF> data;
556 QVector<QwtIntervalSample> dataHisto;
560 myBinX = myHistogram.
minimum + myBinXStep / 2.0;
562 for (
int myBin = 0; myBin < myHistogram.
binCount; myBin++ )
567 data << QPointF( myBinX, myBinValue );
571 dataHisto << QwtIntervalSample( myBinValue, myBinX - myBinXStep / 2.0, myBinX + myBinXStep / 2.0 );
573 myBinX += myBinXStep;
578 mypCurve->setSamples( data );
579 mypCurve->attach( mpPlot );
583 mypHisto->setSamples( dataHisto );
584 mypHisto->attach( mpPlot );
587 if ( myFirstIteration || mHistoMin > myHistogram.
minimum )
589 mHistoMin = myHistogram.
minimum;
591 if ( myFirstIteration || mHistoMax < myHistogram.
maximum )
593 mHistoMax = myHistogram.
maximum;
595 QgsDebugMsgLevel( QStringLiteral(
"computed histo min = %1 max = %2" ).arg( mHistoMin ).arg( mHistoMax ), 2 );
596 myFirstIteration =
false;
599 if ( mHistoMin < mHistoMax )
605 mpPlot->setAxisScale( QwtPlot::xBottom, mHistoMin - myBinXStep / 2, mHistoMax + myBinXStep / 2 );
606 mpPlot->setEnabled(
true );
611 mHistoMarkerMin =
new QwtPlotMarker();
612 mHistoMarkerMin->attach( mpPlot );
613 mHistoMarkerMax =
new QwtPlotMarker();
614 mHistoMarkerMax->attach( mpPlot );
615 updateHistoMarkers();
620 mHistoPicker =
new QwtPlotPicker( mpPlot->canvas() );
622 mHistoPicker->setTrackerMode( QwtPicker::AlwaysOff );
623 mHistoPicker->setRubberBand( QwtPicker::VLineRubberBand );
624 mHistoPicker->setStateMachine(
new QwtPickerDragPointMachine );
625 connect( mHistoPicker,
static_cast<void ( QwtPlotPicker::* )(
const QPointF & )
>( &QwtPlotPicker::selected ),
this, &QgsRasterHistogramWidget::histoPickerSelected );
627 mHistoPicker->setEnabled(
false );
632 mHistoZoomer =
new QwtPlotZoomer( mpPlot->canvas() );
633 mHistoZoomer->setStateMachine(
new QwtPickerDragRectMachine );
634 mHistoZoomer->setTrackerMode( QwtPicker::AlwaysOff );
636 mHistoZoomer->setEnabled(
true );
640 mpPlot->setDisabled(
true );
642 mHistoPicker->setEnabled(
false );
644 mHistoZoomer->setEnabled(
false );
647 stackedWidget2->setCurrentIndex( 0 );
651 QApplication::restoreOverrideCursor();
654void QgsRasterHistogramWidget::mSaveAsImageButton_clicked()
660 const QFileInfo myInfo( myFileNameAndFilter.first );
661 if ( !myInfo.baseName().isEmpty() )
670 const QFileInfo myInfo( filename );
671 const QDir myDir( myInfo.dir() );
672 if ( !myDir.exists() )
674 QgsDebugError( QStringLiteral(
"Error, directory %1 non-existent (theFilename = %2)" ).arg( myDir.absolutePath(), filename ) );
679 QPixmap myPixmap( width, height );
680 const QRect myQRect( 5, 5, width - 10, height - 10 );
681 myPixmap.fill( Qt::white );
683 QwtPlotRenderer myRenderer;
684 myRenderer.setDiscardFlags( QwtPlotRenderer::DiscardBackground | QwtPlotRenderer::DiscardCanvasBackground );
685 myRenderer.setLayoutFlags( QwtPlotRenderer::FrameWithScales );
688 myPainter.begin( &myPixmap );
689 myRenderer.render( mpPlot, &myPainter, myQRect );
693 myPixmap.save( filename,
nullptr, quality );
701 cboHistoBand->setCurrentIndex( bandNo - 1 );
704void QgsRasterHistogramWidget::cboHistoBand_currentIndexChanged(
int index )
706 if ( mHistoShowBands == ShowSelected )
710 index = cboHistoBand->currentIndex();
713 mHistoPicker->setEnabled(
false );
714 mHistoPicker->setRubberBandPen( QPen( mHistoColors.at( index + 1 ) ) );
717 mHistoZoomer->setEnabled(
true );
718 btnHistoMin->setEnabled(
true );
719 btnHistoMax->setEnabled(
true );
721 const QPair<QString, QString> myMinMax = rendererMinMax( index + 1 );
722 leHistoMin->setText( myMinMax.first );
723 leHistoMax->setText( myMinMax.second );
729void QgsRasterHistogramWidget::histoActionTriggered( QAction *action )
733 histoAction( action->data().toString(), action->isChecked() );
738 if ( actionName.isEmpty() )
742 QgsDebugMsgLevel( QStringLiteral(
"band = %1 action = %2" ).arg( cboHistoBand->currentIndex() + 1 ).arg( actionName ), 2 );
745 if ( actionName == QLatin1String(
"Show markers" ) )
747 mHistoShowMarkers = actionFlag;
749 settings.
setValue( QStringLiteral(
"Raster/histogram/showMarkers" ), mHistoShowMarkers );
750 updateHistoMarkers();
753 else if ( actionName == QLatin1String(
"Zoom min_max" ) )
755 mHistoZoomToMinMax = actionFlag;
757 settings.
setValue( QStringLiteral(
"Raster/histogram/zoomToMinMax" ), mHistoZoomToMinMax );
760 else if ( actionName == QLatin1String(
"Update min_max" ) )
762 mHistoUpdateStyleToMinMax = actionFlag;
764 settings.
setValue( QStringLiteral(
"Raster/histogram/updateStyleToMinMax" ), mHistoUpdateStyleToMinMax );
767 else if ( actionName == QLatin1String(
"Show all" ) )
769 mHistoShowBands = ShowAll;
774 else if ( actionName == QLatin1String(
"Show selected" ) )
776 mHistoShowBands = ShowSelected;
781 else if ( actionName == QLatin1String(
"Show RGB" ) )
783 mHistoShowBands = ShowRGB;
788 else if ( actionName == QLatin1String(
"Draw lines" ) )
790 mHistoDrawLines = actionFlag;
792 settings.
setValue( QStringLiteral(
"Raster/histogram/drawLines" ), mHistoDrawLines );
793 btnHistoCompute_clicked();
797 else if ( actionName ==
"Load apply all" )
799 mHistoLoadApplyAll = actionFlag;
800 settings.setValue(
"/Raster/histogram/loadApplyAll", mHistoLoadApplyAll );
806 else if ( actionName.left( 5 ) == QLatin1String(
"Load " ) && mRendererWidget )
808 QVector<int> myBands;
812 double minMaxValues[2];
815 if ( mHistoLoadApplyAll )
817 int myBandCountInt = mRasterLayer->bandCount();
818 for (
int i = 1; i <= myBandCountInt; i++ )
820 if ( i != cboHistoBand->currentIndex() + 1 )
827 myBands << cboHistoBand->currentIndex() + 1;
831 double myStdDev = 1.0;
832 if ( actionName ==
"Load stddev" )
834 myStdDev = mRendererWidget->stdDev().toDouble();
839 leHistoMin->blockSignals(
true );
840 leHistoMax->blockSignals(
true );
843 const auto constMyBands = myBands;
844 for (
const int bandNo : constMyBands )
848 if ( actionName ==
"Load actual" )
850 ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::Actual,
851 bandNo, minMaxValues );
853 else if ( actionName ==
"Load estimate" )
855 ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::Estimate,
856 bandNo, minMaxValues );
858 else if ( actionName ==
"Load extent" )
860 ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::CurrentExtent,
861 bandNo, minMaxValues );
863 else if ( actionName ==
"Load 1 stddev" ||
864 actionName ==
"Load stddev" )
866 ok = mRendererWidget->bandMinMaxFromStdDev( myStdDev, bandNo, minMaxValues );
871 cboHistoBand->setCurrentIndex( bandNo - 1 );
872 if ( !ok || actionName == QLatin1String(
"Load reset" ) )
880 (
Qgis::DataType ) mRasterLayer->dataProvider()->dataType( bandNo ) );
882 (
Qgis::DataType ) mRasterLayer->dataProvider()->dataType( bandNo ) );
886 leHistoMin->setText( QString::number( minMaxValues[0] ) );
887 leHistoMax->setText( QString::number( minMaxValues[1] ) );
894 leHistoMin->blockSignals(
false );
895 leHistoMax->blockSignals(
false );
896 updateHistoMarkers();
898 else if ( actionName == QLatin1String(
"Compute histogram" ) )
900 btnHistoCompute_clicked();
909void QgsRasterHistogramWidget::applyHistoMin()
911 if ( !mRendererWidget )
914 const int bandNo = cboHistoBand->currentIndex() + 1;
915 const QList<int> selectedBands = rendererSelectedBands();
917 for (
int i = 0; i <= selectedBands.size(); i++ )
921 min = leHistoMin->text();
922 if ( mHistoUpdateStyleToMinMax && mRendererWidget->
min( i ) != min )
924 mRendererWidget->
setMin( min, i );
929 if ( mRendererWidget->minMaxWidget() )
931 mRendererWidget->minMaxWidget()->userHasSetManualMinMaxValues();
937 updateHistoMarkers();
939 if ( !min.isEmpty() && mHistoZoomToMinMax && mHistoZoomer )
941 QRectF rect = mHistoZoomer->zoomRect();
942 rect.setLeft( min.toDouble() );
943 mHistoZoomer->zoom( rect );
948void QgsRasterHistogramWidget::applyHistoMax()
950 if ( !mRendererWidget )
953 const int bandNo = cboHistoBand->currentIndex() + 1;
954 const QList<int> mySelectedBands = rendererSelectedBands();
956 for (
int i = 0; i <= mySelectedBands.size(); i++ )
958 if ( bandNo == mRendererWidget->selectedBand( i ) )
960 max = leHistoMax->text();
961 if ( mHistoUpdateStyleToMinMax && mRendererWidget->max( i ) != max )
963 mRendererWidget->setMax( max, i );
968 if ( mRendererWidget->minMaxWidget() )
970 mRendererWidget->minMaxWidget()->userHasSetManualMinMaxValues();
976 updateHistoMarkers();
978 if ( !max.isEmpty() && mHistoZoomToMinMax && mHistoZoomer )
980 QRectF rect = mHistoZoomer->zoomRect();
981 rect.setRight( max.toDouble() );
982 mHistoZoomer->zoom( rect );
987void QgsRasterHistogramWidget::btnHistoMin_toggled()
989 if ( mpPlot && mHistoPicker )
991 if ( QApplication::overrideCursor() )
992 QApplication::restoreOverrideCursor();
993 if ( btnHistoMin->isChecked() )
995 btnHistoMax->setChecked(
false );
996 QApplication::setOverrideCursor( Qt::PointingHandCursor );
999 mHistoZoomer->setEnabled( !btnHistoMin->isChecked() );
1000 mHistoPicker->setEnabled( btnHistoMin->isChecked() );
1002 updateHistoMarkers();
1005void QgsRasterHistogramWidget::btnHistoMax_toggled()
1007 if ( mpPlot && mHistoPicker )
1009 if ( QApplication::overrideCursor() )
1010 QApplication::restoreOverrideCursor();
1011 if ( btnHistoMax->isChecked() )
1013 btnHistoMin->setChecked(
false );
1014 QApplication::setOverrideCursor( Qt::PointingHandCursor );
1017 mHistoZoomer->setEnabled( !btnHistoMax->isChecked() );
1018 mHistoPicker->setEnabled( btnHistoMax->isChecked() );
1020 updateHistoMarkers();
1030 QList<double> minorTicks = scale->ticks( QwtScaleDiv::MinorTick );
1031 QList<double> majorTicks = scale->ticks( QwtScaleDiv::MajorTick );
1032 const double diff = ( minorTicks[1] - minorTicks[0] ) / div;
1033 double min = majorTicks[0] - diff;
1035 min -= ( majorTicks[1] - majorTicks[0] );
1036 const double max = scale->upperBound();
1037 double closest = target;
1038 double current = min;
1040 while ( current < max )
1043 if ( current > target )
1045 closest = ( std::fabs( target - current + diff ) < std::fabs( target - current ) ) ? current - diff : current;
1051 return QLocale().toString( closest );
1054void QgsRasterHistogramWidget::histoPickerSelected( QPointF pos )
1056 if ( btnHistoMin->isChecked() || btnHistoMax->isChecked() )
1058 const QwtScaleDiv *scale = &mpPlot->axisScaleDiv( QwtPlot::xBottom );
1060 if ( btnHistoMin->isChecked() )
1064 btnHistoMin->setChecked(
false );
1070 btnHistoMax->setChecked(
false );
1073 if ( QApplication::overrideCursor() )
1074 QApplication::restoreOverrideCursor();
1077void QgsRasterHistogramWidget::histoPickerSelectedQwt5(
QwtDoublePoint pos )
1079 histoPickerSelected( QPointF( pos.x(), pos.y() ) );
1082void QgsRasterHistogramWidget::updateHistoMarkers()
1085 if ( leHistoMin->signalsBlocked() )
1088 if ( !mpPlot || !mHistoMarkerMin || !mHistoMarkerMax )
1091 const int bandNo = cboHistoBand->currentIndex() + 1;
1092 const QList<int> mySelectedBands = histoSelectedBands();
1094 if ( ( !mHistoShowMarkers && !btnHistoMin->isChecked() && !btnHistoMax->isChecked() ) || ( !mySelectedBands.isEmpty() && !mySelectedBands.contains( bandNo ) ) )
1096 mHistoMarkerMin->hide();
1097 mHistoMarkerMax->hide();
1102 double minVal = mHistoMin;
1103 double maxVal = mHistoMax;
1104 const QString minStr = leHistoMin->text();
1105 const QString maxStr = leHistoMax->text();
1106 if ( !minStr.isEmpty() )
1107 minVal = minStr.toDouble();
1108 if ( !maxStr.isEmpty() )
1109 maxVal = maxStr.toDouble();
1111 QPen linePen = QPen( mHistoColors.at( bandNo ) );
1112 linePen.setStyle( Qt::DashLine );
1113 mHistoMarkerMin->setLineStyle( QwtPlotMarker::VLine );
1114 mHistoMarkerMin->setLinePen( linePen );
1115 mHistoMarkerMin->setXValue( minVal );
1116 mHistoMarkerMin->show();
1117 mHistoMarkerMax->setLineStyle( QwtPlotMarker::VLine );
1118 mHistoMarkerMax->setLinePen( linePen );
1119 mHistoMarkerMax->setXValue( maxVal );
1120 mHistoMarkerMax->show();
1126QList<int> QgsRasterHistogramWidget::histoSelectedBands()
1128 QList<int> mySelectedBands;
1130 if ( mHistoShowBands != ShowAll )
1132 if ( mHistoShowBands == ShowSelected )
1134 mySelectedBands << cboHistoBand->currentIndex() + 1;
1136 else if ( mHistoShowBands == ShowRGB )
1138 mySelectedBands = rendererSelectedBands();
1142 return mySelectedBands;
1145QList<int> QgsRasterHistogramWidget::rendererSelectedBands()
1147 QList<int> mySelectedBands;
1149 if ( !mRendererWidget )
1151 mySelectedBands << -1 << -1 << -1;
1152 return mySelectedBands;
1155 if ( mRendererName == QLatin1String(
"singlebandgray" ) || mRendererName == QLatin1String(
"singlebandpseudocolor" ) )
1157 mySelectedBands << mRendererWidget->selectedBand();
1159 else if ( mRendererName == QLatin1String(
"multibandcolor" ) )
1161 for (
int i = 0; i <= 2; i++ )
1163 mySelectedBands << mRendererWidget->selectedBand( i );
1167 return mySelectedBands;
1170QPair<QString, QString> QgsRasterHistogramWidget::rendererMinMax(
int bandNo )
1172 QPair<QString, QString> myMinMax;
1174 if ( !mRendererWidget )
1177 if ( mRendererName == QLatin1String(
"singlebandgray" ) || mRendererName == QLatin1String(
"singlebandpseudocolor" ) )
1179 if ( bandNo == mRendererWidget->selectedBand() )
1181 myMinMax.first = mRendererWidget->min();
1182 myMinMax.second = mRendererWidget->max();
1185 else if ( mRendererName == QLatin1String(
"multibandcolor" ) )
1187 for (
int i = 0; i <= 2; i++ )
1189 if ( bandNo == mRendererWidget->selectedBand( i ) )
1191 myMinMax.first = mRendererWidget->min( i );
1192 myMinMax.second = mRendererWidget->max( i );
1208 if ( myMinMax.first.isEmpty() )
1209 myMinMax.first = QLocale().toString( mHistoMin );
1210 if ( myMinMax.second.isEmpty() )
1211 myMinMax.second = QLocale().toString( mHistoMax );
1213 QgsDebugMsgLevel( QStringLiteral(
"bandNo %1 got min/max [%2] [%3]" ).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.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
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)