Skip to content
Permalink
Browse files

new widget for raster min/max load

  • Loading branch information
blazek committed Jul 28, 2012
1 parent 64d1c02 commit 3d8e3bd4da256e6d51220fd75f97720dc801cc96
@@ -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 )
{
@@ -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() ) );
@@ -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() )
@@ -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 );

@@ -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 )
@@ -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,
@@ -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
{
@@ -1,6 +1,7 @@

SET(QGIS_GUI_SRCS

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

SET(QGIS_GUI_MOC_HDRS

raster/qgsrasterminmaxwidget.h
raster/qgspalettedrendererwidget.h
raster/qgsmultibandcolorrendererwidget.h
raster/qgssinglebandgrayrendererwidget.h
@@ -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();
@@ -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 );
@@ -53,6 +66,7 @@ QgsMultiBandColorRendererWidget::QgsMultiBandColorRendererWidget( QgsRasterLayer
}

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

@@ -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 )
@@ -18,6 +18,7 @@
#ifndef QGSMULTIBANDCOLORRENDERERWIDGET_H
#define QGSMULTIBANDCOLORRENDERERWIDGET_H

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

@@ -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();
@@ -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
@@ -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 );

@@ -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();

0 comments on commit 3d8e3bd

Please sign in to comment.
You can’t perform that action at this time.