Skip to content

Commit

Permalink
new widget for raster min/max load
Browse files Browse the repository at this point in the history
  • Loading branch information
blazek committed Jul 28, 2012
1 parent 64d1c02 commit 3d8e3bd
Show file tree
Hide file tree
Showing 24 changed files with 610 additions and 428 deletions.
4 changes: 3 additions & 1 deletion src/app/qgsrasterlayerproperties.cpp
Expand Up @@ -410,7 +410,9 @@ void QgsRasterLayerProperties::setRendererWidget( const QString& rendererName )
{
if ( rendererEntry.widgetCreateFunction ) //single band color data renderer e.g. has no widget
{
mRendererWidget = ( *rendererEntry.widgetCreateFunction )( mRasterLayer );
// Current canvas extent (used to calc min/max) in layer CRS
QgsRectangle myExtent = mMapCanvas->mapRenderer()->outputExtentToLayerExtent( mRasterLayer, mMapCanvas->extent() );
mRendererWidget = ( *rendererEntry.widgetCreateFunction )( mRasterLayer, myExtent );
mRendererStackedWidget->addWidget( mRendererWidget );
if ( oldWidget )
{
Expand Down
23 changes: 22 additions & 1 deletion src/core/qgsmaprenderer.cpp
Expand Up @@ -767,7 +767,6 @@ bool QgsMapRenderer::splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent
return split;
}


QgsRectangle QgsMapRenderer::layerExtentToOutputExtent( QgsMapLayer* theLayer, QgsRectangle extent )
{
QgsDebugMsg( QString( "sourceCrs = " + tr( theLayer )->sourceCrs().authid() ) );
Expand All @@ -790,6 +789,28 @@ QgsRectangle QgsMapRenderer::layerExtentToOutputExtent( QgsMapLayer* theLayer, Q
return extent;
}

QgsRectangle QgsMapRenderer::outputExtentToLayerExtent( QgsMapLayer* theLayer, QgsRectangle extent )
{
QgsDebugMsg( QString( "layer sourceCrs = " + tr( theLayer )->sourceCrs().authid() ) );
QgsDebugMsg( QString( "layer destCRS = " + tr( theLayer )->destCRS().authid() ) );
QgsDebugMsg( QString( "extent = " + extent.toString() ) );
if ( hasCrsTransformEnabled() )
{
try
{
extent = tr( theLayer )->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
}
catch ( QgsCsException &cse )
{
QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
}
}

QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );

return extent;
}

QgsPoint QgsMapRenderer::layerToMapCoordinates( QgsMapLayer* theLayer, QgsPoint point )
{
if ( hasCrsTransformEnabled() )
Expand Down
3 changes: 3 additions & 0 deletions src/core/qgsmaprenderer.h
Expand Up @@ -168,6 +168,9 @@ class CORE_EXPORT QgsMapRenderer : public QObject
//! transform extent in layer's CRS to extent in output CRS
QgsRectangle layerExtentToOutputExtent( QgsMapLayer* theLayer, QgsRectangle extent );

//! transform extent in output CRS to extent in layer's CRS
QgsRectangle outputExtentToLayerExtent( QgsMapLayer* theLayer, QgsRectangle extent );

//! transform coordinates from layer's CRS to output CRS
QgsPoint layerToMapCoordinates( QgsMapLayer* theLayer, QgsPoint point );

Expand Down
38 changes: 38 additions & 0 deletions src/core/qgsrasterdataprovider.cpp
Expand Up @@ -869,6 +869,44 @@ QgsRasterHistogram QgsRasterDataProvider::histogram( int theBandNo,
return myHistogram;
}

void QgsRasterDataProvider::cumulativeCut( int theBandNo,
double theLowerCount, double theUpperCount,
double &theLowerValue, double &theUpperValue,
const QgsRectangle & theExtent,
int theSampleSize )
{
QgsDebugMsg( QString( "theBandNo = %1 theLowerCount = %2 theUpperCount = %3 theSampleSize = %4" ).arg( theBandNo ).arg( theLowerCount ).arg( theUpperCount ).arg( theSampleSize ) );

QgsRasterHistogram myHistogram = histogram( theBandNo, 0, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), theExtent, theSampleSize );

// Init to NaN is better than histogram min/max to catch errors
theLowerValue = std::numeric_limits<double>::quiet_NaN();
theUpperValue = std::numeric_limits<double>::quiet_NaN();

double myBinXStep = ( myHistogram.maximum - myHistogram.minimum ) / myHistogram.binCount;
int myCount = 0;
int myMinCount = ( int ) qRound( theLowerCount * myHistogram.nonNullCount );
int myMaxCount = ( int ) qRound( theUpperCount * myHistogram.nonNullCount );
bool myLowerFound = false;
QgsDebugMsg( QString( "binCount = %1 minimum = %2 maximum = %3 myBinXStep = %4" ).arg( myHistogram.binCount ).arg( myHistogram.minimum ).arg( myHistogram.maximum ).arg( myBinXStep ) );

for ( int myBin = 0; myBin < myHistogram.histogramVector.size(); myBin++ )
{
int myBinValue = myHistogram.histogramVector.value( myBin );
myCount += myBinValue;
if ( !myLowerFound && myCount > myMinCount )
{
theLowerValue = myHistogram.minimum + myBin * myBinXStep;
myLowerFound = true;
}
if ( myCount >= myMaxCount )
{
theUpperValue = myHistogram.minimum + myBin * myBinXStep;
break;
}
}
}

double QgsRasterDataProvider::readValue( void *data, int type, int index )
{
if ( !data )
Expand Down
16 changes: 16 additions & 0 deletions src/core/qgsrasterdataprovider.h
Expand Up @@ -322,6 +322,22 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
int theSampleSize = 0,
bool theIncludeOutOfRange = false );

/** \brief Find values for cumulative pixel count cut.
* @param theBandNo The band (number).
* @param theLowerCount The lower count as fraction of 1, e.g. 0.02 = 2%
* @param theUpperCount The upper count as fraction of 1, e.g. 0.98 = 98%
* @param theLowerValue Location into which the lower value will be set.
* @param theUpperValue Location into which the upper value will be set.
* @param theExtent Extent used to calc histogram, if empty, whole raster extent is used.
* @param theSampleSize Approximate number of cells in sample. If 0, all cells (whole raster will be used). If raster does not have exact size (WCS without exact size for example), provider decides size of sample.
*/
virtual void cumulativeCut( int theBandNo,
double theLowerCount,
double theUpperCount,
double &theLowerValue,
double &theUpperValue,
const QgsRectangle & theExtent = QgsRectangle(),
int theSampleSize = 0 );

/** \brief Create pyramid overviews */
virtual QString buildPyramids( const QList<QgsRasterPyramid> & thePyramidList,
Expand Down
2 changes: 1 addition & 1 deletion src/core/raster/qgsrasterrendererregistry.h
Expand Up @@ -30,7 +30,7 @@ class QgsRasterRenderer;
class QgsRasterRendererWidget;

typedef QgsRasterRenderer*( *QgsRasterRendererCreateFunc )( const QDomElement&, QgsRasterInterface* input );
typedef QgsRasterRendererWidget*( *QgsRasterRendererWidgetCreateFunc )( QgsRasterLayer* );
typedef QgsRasterRendererWidget*( *QgsRasterRendererWidgetCreateFunc )( QgsRasterLayer*, const QgsRectangle &extent );

struct CORE_EXPORT QgsRasterRendererRegistryEntry
{
Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
@@ -1,6 +1,7 @@

SET(QGIS_GUI_SRCS

raster/qgsrasterminmaxwidget.cpp
raster/qgsrasterrendererwidget.cpp
raster/qgsmultibandcolorrendererwidget.cpp
raster/qgspalettedrendererwidget.cpp
Expand Down Expand Up @@ -100,6 +101,7 @@ ENDIF (WITH_TOUCH)

SET(QGIS_GUI_MOC_HDRS

raster/qgsrasterminmaxwidget.h
raster/qgspalettedrendererwidget.h
raster/qgsmultibandcolorrendererwidget.h
raster/qgssinglebandgrayrendererwidget.h
Expand Down
109 changes: 64 additions & 45 deletions src/gui/raster/qgsmultibandcolorrendererwidget.cpp
Expand Up @@ -19,7 +19,7 @@
#include "qgsmultibandcolorrenderer.h"
#include "qgsrasterlayer.h"

QgsMultiBandColorRendererWidget::QgsMultiBandColorRendererWidget( QgsRasterLayer* layer ): QgsRasterRendererWidget( layer )
QgsMultiBandColorRendererWidget::QgsMultiBandColorRendererWidget( QgsRasterLayer* layer, const QgsRectangle &extent ): QgsRasterRendererWidget( layer, extent )
{
setupUi( this );
createValidators();
Expand All @@ -32,6 +32,19 @@ QgsMultiBandColorRendererWidget::QgsMultiBandColorRendererWidget( QgsRasterLayer
return;
}

mMinMaxWidget = new QgsRasterMinMaxWidget( layer, this );
mMinMaxWidget->setExtent( extent );
layout()->addWidget( mMinMaxWidget );
connect( mMinMaxWidget, SIGNAL( load( int, double, double ) ),
this, SLOT( loadMinMax( int, double, double ) ) );

connect( mRedBandComboBox, SIGNAL( currentIndexChanged( int ) ),
this, SLOT( onBandChanged( int ) ) );
connect( mGreenBandComboBox, SIGNAL( currentIndexChanged( int ) ),
this, SLOT( onBandChanged( int ) ) );
connect( mBlueBandComboBox, SIGNAL( currentIndexChanged( int ) ),
this, SLOT( onBandChanged( int ) ) );

//fill available bands into combo boxes
mRedBandComboBox->addItem( tr( "Not set" ), -1 );
mGreenBandComboBox->addItem( tr( "Not set" ), -1 );
Expand All @@ -53,6 +66,7 @@ QgsMultiBandColorRendererWidget::QgsMultiBandColorRendererWidget( QgsRasterLayer
}

setFromRenderer( mRasterLayer->renderer() );
onBandChanged( 0 ); // reset mMinMaxWidget bands
}
}

Expand Down Expand Up @@ -166,77 +180,82 @@ void QgsMultiBandColorRendererWidget::setCustomMinMaxValues( QgsMultiBandColorRe
r->setBlueContrastEnhancement( blueEnhancement );
}

void QgsMultiBandColorRendererWidget::on_mLoadPushButton_clicked()
void QgsMultiBandColorRendererWidget::onBandChanged( int index )
{
int redBand = mRedBandComboBox->itemData( mRedBandComboBox->currentIndex() ).toInt();
int greenBand = mGreenBandComboBox->itemData( mGreenBandComboBox->currentIndex() ).toInt();
int blueBand = mBlueBandComboBox->itemData( mBlueBandComboBox->currentIndex() ).toInt();

loadMinMaxValueForBand( redBand, mRedMinLineEdit, mRedMaxLineEdit );
loadMinMaxValueForBand( greenBand, mGreenMinLineEdit, mGreenMaxLineEdit );
loadMinMaxValueForBand( blueBand, mBlueMinLineEdit, mBlueMaxLineEdit );
QList<int> myBands;
myBands.append( mRedBandComboBox->itemData( mRedBandComboBox->currentIndex() ).toInt() );
myBands.append( mGreenBandComboBox->itemData( mGreenBandComboBox->currentIndex() ).toInt() );
myBands.append( mBlueBandComboBox->itemData( mBlueBandComboBox->currentIndex() ).toInt() );
mMinMaxWidget->setBands( myBands );
}

void QgsMultiBandColorRendererWidget::setMinMaxValue( const QgsContrastEnhancement* ce, QLineEdit* minEdit, QLineEdit* maxEdit )
void QgsMultiBandColorRendererWidget::loadMinMax( int theBandNo, double theMin, double theMax )
{
if ( !minEdit || !maxEdit )
QgsDebugMsg( QString( "theBandNo = %1 theMin = %2 theMax = %3" ).arg( theBandNo ).arg( theMin ).arg( theMax ) );

QLineEdit *myMinLineEdit, *myMaxLineEdit;

if ( mRedBandComboBox->itemData( mRedBandComboBox->currentIndex() ).toInt() == theBandNo )
{
return;
myMinLineEdit = mRedMinLineEdit;
myMaxLineEdit = mRedMaxLineEdit;
}

if ( !ce )
else if ( mGreenBandComboBox->itemData( mGreenBandComboBox->currentIndex() ).toInt() == theBandNo )
{
minEdit->clear();
maxEdit->clear();
return;
myMinLineEdit = mGreenMinLineEdit;
myMaxLineEdit = mGreenMaxLineEdit;
}

minEdit->setText( QString::number( ce->minimumValue() ) );
maxEdit->setText( QString::number( ce->maximumValue() ) );
mContrastEnhancementAlgorithmComboBox->setCurrentIndex( mContrastEnhancementAlgorithmComboBox->findData(
( int )( ce->contrastEnhancementAlgorithm() ) ) );
}

void QgsMultiBandColorRendererWidget::loadMinMaxValueForBand( int band, QLineEdit* minEdit, QLineEdit* maxEdit )
{
if ( !minEdit || !maxEdit || !mRasterLayer )
else if ( mBlueBandComboBox->itemData( mBlueBandComboBox->currentIndex() ).toInt() == theBandNo )
{
myMinLineEdit = mBlueMinLineEdit;
myMaxLineEdit = mBlueMaxLineEdit;
}
else // should not happen
{
QgsDebugMsg( "Band not found" );
return;
}

double minMaxValues[2];
bool ok = false;

if ( mEstimateRadioButton->isChecked() )
if ( qIsNaN( theMin ) )
{
ok = bandMinMax( Estimate, band, minMaxValues );
myMinLineEdit->clear();
}
else if ( mActualRadioButton->isChecked() )
else
{
ok = bandMinMax( Actual, band, minMaxValues );
myMinLineEdit->setText( QString::number( theMin ) );
}
else if ( mCurrentExtentRadioButton->isChecked() )

if ( qIsNaN( theMax ) )
{
ok = bandMinMax( CurrentExtent, band, minMaxValues );
myMaxLineEdit->clear();
}
else if ( mUseStdDevRadioButton->isChecked() )
else
{
QgsRasterBandStats rasterBandStats = mRasterLayer->dataProvider()->bandStatistics( band );
double diff = mStdDevSpinBox->value() * rasterBandStats.stdDev;
minMaxValues[0] = rasterBandStats.mean - diff;
minMaxValues[1] = rasterBandStats.mean + diff;
myMaxLineEdit->setText( QString::number( theMax ) );
}
}

if ( ok )
void QgsMultiBandColorRendererWidget::setMinMaxValue( const QgsContrastEnhancement* ce, QLineEdit* minEdit, QLineEdit* maxEdit )
{
if ( !minEdit || !maxEdit )
{
minEdit->setText( QString::number( minMaxValues[0] ) );
maxEdit->setText( QString::number( minMaxValues[1] ) );
return;
}
else

if ( !ce )
{
minEdit->clear();
maxEdit->clear();
return;
}

minEdit->setText( QString::number( ce->minimumValue() ) );
maxEdit->setText( QString::number( ce->maximumValue() ) );

// QgsMultiBandColorRenderer is using individual contrast enhancements for each
// band, but this widget GUI has one for all
mContrastEnhancementAlgorithmComboBox->setCurrentIndex( mContrastEnhancementAlgorithmComboBox->findData(
( int )( ce->contrastEnhancementAlgorithm() ) ) );
}

void QgsMultiBandColorRendererWidget::setFromRenderer( const QgsRasterRenderer* r )
Expand Down
17 changes: 11 additions & 6 deletions src/gui/raster/qgsmultibandcolorrendererwidget.h
Expand Up @@ -18,6 +18,7 @@
#ifndef QGSMULTIBANDCOLORRENDERERWIDGET_H
#define QGSMULTIBANDCOLORRENDERERWIDGET_H

#include "qgsrasterminmaxwidget.h"
#include "qgsrasterrendererwidget.h"
#include "ui_qgsmultibandcolorrendererwidgetbase.h"

Expand All @@ -32,8 +33,8 @@ class GUI_EXPORT QgsMultiBandColorRendererWidget: public QgsRasterRendererWidget
Q_OBJECT

public:
QgsMultiBandColorRendererWidget( QgsRasterLayer* layer );
static QgsRasterRendererWidget* create( QgsRasterLayer* layer ) { return new QgsMultiBandColorRendererWidget( layer ); }
QgsMultiBandColorRendererWidget( QgsRasterLayer* layer, const QgsRectangle &extent = QgsRectangle() );
static QgsRasterRendererWidget* create( QgsRasterLayer* layer, const QgsRectangle &theExtent ) { return new QgsMultiBandColorRendererWidget( layer, theExtent ); }
~QgsMultiBandColorRendererWidget();

QgsRasterRenderer* renderer();
Expand All @@ -44,20 +45,24 @@ class GUI_EXPORT QgsMultiBandColorRendererWidget: public QgsRasterRendererWidget
QString max( int index = 0 );
void setMin( QString value, int index = 0 );
void setMax( QString value, int index = 0 );
QString stdDev( ) { return QString::number( mStdDevSpinBox->value() ); }
void setStdDev( QString value ) { mStdDevSpinBox->setValue( value.toDouble() ); }
//QString stdDev( ) { return QString::number( mStdDevSpinBox->value() ); }
//void setStdDev( QString value ) { mStdDevSpinBox->setValue( value.toDouble() ); }
int selectedBand( int index = 0 );

public slots:
void loadMinMax( int theBandNo, double theMin, double theMax );

private slots:
void on_mLoadPushButton_clicked();
//void on_mLoadPushButton_clicked();
void onBandChanged( int );

private:
void createValidators();
void setCustomMinMaxValues( QgsMultiBandColorRenderer* r, const QgsRasterDataProvider* provider, int redBand, int GreenBand,
int blueBand );
/**Reads min/max values from contrast enhancement and fills values into the min/max line edits*/
void setMinMaxValue( const QgsContrastEnhancement* ce, QLineEdit* minEdit, QLineEdit* maxEdit );
void loadMinMaxValueForBand( int band, QLineEdit* minEdit, QLineEdit* maxEdit );
QgsRasterMinMaxWidget * mMinMaxWidget;
};

#endif // QGSMULTIBANDCOLORRENDERERWIDGET_H
2 changes: 1 addition & 1 deletion src/gui/raster/qgspalettedrendererwidget.cpp
Expand Up @@ -20,7 +20,7 @@
#include "qgsrasterlayer.h"
#include <QColorDialog>

QgsPalettedRendererWidget::QgsPalettedRendererWidget( QgsRasterLayer* layer ): QgsRasterRendererWidget( layer )
QgsPalettedRendererWidget::QgsPalettedRendererWidget( QgsRasterLayer* layer, const QgsRectangle &extent ): QgsRasterRendererWidget( layer, extent )
{
setupUi( this );

Expand Down
4 changes: 2 additions & 2 deletions src/gui/raster/qgspalettedrendererwidget.h
Expand Up @@ -28,8 +28,8 @@ class GUI_EXPORT QgsPalettedRendererWidget: public QgsRasterRendererWidget, priv
Q_OBJECT

public:
QgsPalettedRendererWidget( QgsRasterLayer* layer );
static QgsRasterRendererWidget* create( QgsRasterLayer* layer ) { return new QgsPalettedRendererWidget( layer ); }
QgsPalettedRendererWidget( QgsRasterLayer* layer, const QgsRectangle &extent = QgsRectangle() );
static QgsRasterRendererWidget* create( QgsRasterLayer* layer, const QgsRectangle &theExtent ) { return new QgsPalettedRendererWidget( layer, theExtent ); }
~QgsPalettedRendererWidget();

QgsRasterRenderer* renderer();
Expand Down

0 comments on commit 3d8e3bd

Please sign in to comment.