116 changes: 70 additions & 46 deletions src/core/raster/qgsrasterlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ typedef bool isvalidrasterfilename_t( QString const & theFileNameQString, QStrin
// doubles can take for the current system. (Yes, 20 was arbitrary.)
#define TINY_VALUE std::numeric_limits<double>::epsilon() * 20

const double QgsRasterLayer::CUMULATIVE_CUT_LOWER = 0.02;
const double QgsRasterLayer::CUMULATIVE_CUT_UPPER = 0.98;
const double QgsRasterLayer::SAMPLE_SIZE = 250000;

QgsRasterLayer::QgsRasterLayer()
: QgsMapLayer( RasterLayer )
, QSTRING_NOT_SET( "Not Set" )
Expand Down Expand Up @@ -1845,71 +1849,91 @@ void QgsRasterLayer::setColorShadingAlgorithm( QString )

void QgsRasterLayer::setContrastEnhancementAlgorithm( QgsContrastEnhancement::ContrastEnhancementAlgorithm theAlgorithm, bool theGenerateLookupTableFlag )
{
setContrastEnhancementAlgorithm( theAlgorithm, ContrastEnhancementMinMax, QgsRectangle(), SAMPLE_SIZE, theGenerateLookupTableFlag );
}

void QgsRasterLayer::setContrastEnhancementAlgorithm( QgsContrastEnhancement::ContrastEnhancementAlgorithm theAlgorithm, ContrastEnhancementLimits theLimits, QgsRectangle theExtent, int theSampleSize, bool theGenerateLookupTableFlag )
{
QgsDebugMsg( QString( "theAlgorithm = %1 theLimits = %2 theExtent.isEmpty() = %3" ).arg( theAlgorithm ).arg( theLimits ).arg( theExtent.isEmpty() ) );
if ( !mPipe.renderer() || !mDataProvider )
{
return;
}

QList<int> myBands;
QList<QgsContrastEnhancement*> myEnhancements;
QgsSingleBandGrayRenderer* myGrayRenderer = 0;
QgsMultiBandColorRenderer* myMultiBandRenderer = 0;
QString rendererType = mPipe.renderer()->type();
if ( rendererType == "singlebandgray" )
{
QgsSingleBandGrayRenderer* gr = dynamic_cast<QgsSingleBandGrayRenderer*>( mPipe.renderer() );
if ( gr )
{
int grayBand = gr->grayBand();
if ( grayBand == -1 )
{
return;
}
QgsRasterDataProvider::DataType dataType = ( QgsRasterDataProvider::DataType )mDataProvider->dataType( grayBand );
QgsContrastEnhancement* ce = new QgsContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )dataType );
ce->setContrastEnhancementAlgorithm( theAlgorithm, theGenerateLookupTableFlag );
ce->setMinimumValue( mDataProvider->minimumValue( grayBand ) );
ce->setMaximumValue( mDataProvider->maximumValue( grayBand ) );
gr->setContrastEnhancement( ce );
}
myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer*>( mPipe.renderer() );
if ( !myGrayRenderer ) return;
myBands << myGrayRenderer->grayBand();
}
else if ( rendererType == "multibandcolor" )
{
QgsMultiBandColorRenderer* cr = dynamic_cast<QgsMultiBandColorRenderer*>( mPipe.renderer() );
if ( cr )
myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer*>( mPipe.renderer() );
if ( !myMultiBandRenderer ) return;
myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
}

foreach( int myBand, myBands )
{
if ( myBand != -1 )
{
//red enhancement
int redBand = cr->redBand();
if ( redBand != -1 )
QgsRasterDataProvider::DataType myType = ( QgsRasterDataProvider::DataType )mDataProvider->dataType( myBand );
QgsContrastEnhancement* myEnhancement = new QgsContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )myType );
myEnhancement->setContrastEnhancementAlgorithm( theAlgorithm, theGenerateLookupTableFlag );

double myMin = std::numeric_limits<double>::quiet_NaN();
double myMax = std::numeric_limits<double>::quiet_NaN();

if ( theLimits == ContrastEnhancementMinMax )
{
QgsRasterDataProvider::DataType redType = ( QgsRasterDataProvider::DataType )mDataProvider->dataType( redBand );
QgsContrastEnhancement* redEnhancement = new QgsContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )redType );
redEnhancement->setContrastEnhancementAlgorithm( theAlgorithm, theGenerateLookupTableFlag );
redEnhancement->setMinimumValue( mDataProvider->minimumValue( redBand ) );
redEnhancement->setMaximumValue( mDataProvider->maximumValue( redBand ) );
cr->setRedContrastEnhancement( redEnhancement );
// minimumValue/maximumValue are not well defined (estimation) and will be removed
//myMin = mDataProvider->minimumValue( myBand );
//myMax = mDataProvider->maximumValue( myBand );
QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( myBand, QgsRasterBandStats::Min | QgsRasterBandStats::Max, theExtent, theSampleSize );
myMin = myRasterBandStats.minimumValue;
myMax = myRasterBandStats.maximumValue;
}

//green enhancement
int greenBand = cr->greenBand();
if ( greenBand != -1 )
else if ( theLimits == ContrastEnhancementStdDev )
{
QgsRasterDataProvider::DataType greenType = ( QgsRasterDataProvider::DataType )mDataProvider->dataType( cr->greenBand() );
QgsContrastEnhancement* greenEnhancement = new QgsContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )greenType );
greenEnhancement->setContrastEnhancementAlgorithm( theAlgorithm, theGenerateLookupTableFlag );
greenEnhancement->setMinimumValue( mDataProvider->minimumValue( greenBand ) );
greenEnhancement->setMaximumValue( mDataProvider->maximumValue( greenBand ) );
cr->setGreenContrastEnhancement( greenEnhancement );
double myStdDev = 1; // make optional?
QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( myBand, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, theExtent, theSampleSize );
myMin = myRasterBandStats.mean - ( myStdDev * myRasterBandStats.stdDev );
myMax = myRasterBandStats.mean + ( myStdDev * myRasterBandStats.stdDev );
}

//blue enhancement
int blueBand = cr->blueBand();
if ( blueBand != -1 )
else if ( theLimits == ContrastEnhancementCumulativeCut )
{
QgsRasterDataProvider::DataType blueType = ( QgsRasterDataProvider::DataType )mDataProvider->dataType( cr->blueBand() );
QgsContrastEnhancement* blueEnhancement = new QgsContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )blueType );
blueEnhancement->setContrastEnhancementAlgorithm( theAlgorithm, theGenerateLookupTableFlag );
blueEnhancement->setMinimumValue( mDataProvider->minimumValue( blueBand ) );
blueEnhancement->setMaximumValue( mDataProvider->maximumValue( blueBand ) );
cr->setBlueContrastEnhancement( blueEnhancement );
QSettings mySettings;
double myLower = mySettings.value( "/Raster/cumulativeCutLower", QString::number( CUMULATIVE_CUT_LOWER ) ).toDouble();
double myUpper = mySettings.value( "/Raster/cumulativeCutUpper", QString::number( CUMULATIVE_CUT_UPPER ) ).toDouble();
QgsDebugMsg( QString( "myLower = %1 myUpper = %2" ).arg( myLower ).arg( myUpper ) );
mDataProvider->cumulativeCut( myBand, myLower, myUpper, myMin, myMax, theExtent, theSampleSize );
}

QgsDebugMsg( QString( "myBand = %1 myMin = %2 myMax = %3" ).arg( myBand ).arg( myMin ).arg( myMax ) );
myEnhancement->setMinimumValue( myMin );
myEnhancement->setMaximumValue( myMax );
myEnhancements.append( myEnhancement );
}
else
{
myEnhancements.append( 0 );
}
}

if ( rendererType == "singlebandgray" )
{
if ( myEnhancements.value( 0 ) ) myGrayRenderer->setContrastEnhancement( myEnhancements.value( 0 ) );
}
else if ( rendererType == "multibandcolor" )
{
if ( myEnhancements.value( 0 ) ) myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.value( 0 ) );
if ( myEnhancements.value( 1 ) ) myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.value( 1 ) );
if ( myEnhancements.value( 2 ) ) myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.value( 2 ) );
}
}

Expand Down
36 changes: 34 additions & 2 deletions src/core/raster/qgsrasterlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,15 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
{
Q_OBJECT
public:
/** \brief Default cumulative cut lower limit */
static const double CUMULATIVE_CUT_LOWER;

/** \brief Default cumulative cut upper limit */
static const double CUMULATIVE_CUT_UPPER;

/** \brief Default sample size (number of pixels) for estimated statistics/histogram calculation */
static const double SAMPLE_SIZE;

/** \brief Constructor. Provider is not set. */
QgsRasterLayer();

Expand Down Expand Up @@ -243,7 +252,15 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
Palette,
Multiband,
ColorLayer
} ;
};

/** \brief Contrast enhancement limits */
enum ContrastEnhancementLimits
{
ContrastEnhancementMinMax,
ContrastEnhancementStdDev,
ContrastEnhancementCumulativeCut
};

/** \brief A list containing on ContrastEnhancement object per raster band in this raster layer */
typedef QList<QgsContrastEnhancement> ContrastEnhancementList;
Expand Down Expand Up @@ -548,8 +565,23 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
/** \brief Mutator for color shader algorithm */
Q_DECL_DEPRECATED void setColorShadingAlgorithm( QString theShaderAlgorithm );

/** \brief Mutator for contrast enhancement algorithm */
/** \brief Mutator for contrast enhancement algorithm using min/max */
// TODO: remove in 2.0, replaced by following
void setContrastEnhancementAlgorithm( QgsContrastEnhancement::ContrastEnhancementAlgorithm theAlgorithm,
bool theGenerateLookupTableFlag = true );

/** \brief Mutator for contrast enhancement algorithm
* @param theAlgorithm Contrast enhancement algorithm
* @param theLimits Limits
* @param theExtent Extent used to calculate limits, if empty, use full layer extent
* @param theSampleSize Size of data sample to calculate limits, if 0, use full resolution
* @param theGenerateLookupTableFlag Generate llokup table. */


void setContrastEnhancementAlgorithm( QgsContrastEnhancement::ContrastEnhancementAlgorithm theAlgorithm,
ContrastEnhancementLimits theLimits = ContrastEnhancementMinMax,
QgsRectangle theExtent = QgsRectangle(),
int theSampleSize = SAMPLE_SIZE,
bool theGenerateLookupTableFlag = true );

/** \brief Mutator for contrast enhancement algorithm */
Expand Down
2 changes: 2 additions & 0 deletions src/core/raster/qgsrasterrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "qgsrasterdataprovider.h"
#include <QPair>

#include "cpl_conv.h"

class QPainter;
class QgsMapToPixel;
class QgsRasterResampler;
Expand Down
2 changes: 1 addition & 1 deletion src/gui/raster/qgsrasterminmaxwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ void QgsRasterMinMaxWidget::on_mLoadPushButton_clicked()
}
else if ( mStdDevRadioButton->isChecked() )
{
QgsRasterBandStats myRasterBandStats = mLayer->dataProvider()->bandStatistics( myBand, QgsRasterBandStats::Mean, myExtent, mySampleSize );
QgsRasterBandStats myRasterBandStats = mLayer->dataProvider()->bandStatistics( myBand, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, myExtent, mySampleSize );
double myStdDev = mStdDevSpinBox->value();
myMin = myRasterBandStats.mean - ( myStdDev * myRasterBandStats.stdDev );
myMax = myRasterBandStats.mean + ( myStdDev * myRasterBandStats.stdDev );
Expand Down
1 change: 0 additions & 1 deletion src/plugins/sqlanywhere/sasourceselect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#include "sanewconnection.h"
#include "qgsquerybuilder.h"

#include "qgisapp.h"
#include "qgslogger.h"
#include "qgsapplication.h"
#include "qgscontexthelp.h"
Expand Down
42 changes: 34 additions & 8 deletions src/ui/qgisapp.ui
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<x>0</x>
<y>0</y>
<width>1052</width>
<height>26</height>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="mEditMenu">
Expand Down Expand Up @@ -189,12 +189,6 @@
<addaction name="separator"/>
<addaction name="mActionShowPythonDialog"/>
</widget>
<widget class="QMenu" name="mRasterMenu">
<property name="title">
<string>&amp;Raster</string>
</property>
<addaction name="mActionShowRasterCalculator"/>
</widget>
<widget class="QMenu" name="mHelpMenu">
<property name="title">
<string>&amp;Help</string>
Expand All @@ -220,6 +214,12 @@
<addaction name="mActionOptions"/>
<addaction name="mActionSnappingOptions"/>
</widget>
<widget class="QMenu" name="mRasterMenu">
<property name="title">
<string>&amp;Raster</string>
</property>
<addaction name="mActionShowRasterCalculator"/>
</widget>
<addaction name="mFileMenu"/>
<addaction name="mEditMenu"/>
<addaction name="mViewMenu"/>
Expand Down Expand Up @@ -385,8 +385,10 @@
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="mActionFullHistogramStretch"/>
<addaction name="mActionLocalCumulativeCutStretch"/>
<addaction name="mActionFullCumulativeCutStretch"/>
<addaction name="mActionLocalHistogramStretch"/>
<addaction name="mActionFullHistogramStretch"/>
</widget>
<widget class="QToolBar" name="mLabelToolBar">
<property name="windowTitle">
Expand Down Expand Up @@ -1748,6 +1750,30 @@ Shift thaws, Alt toggles, Ctl (Cmd) hides</string>
<string>New Blank Project</string>
</property>
</action>
<action name="mActionLocalCumulativeCutStretch">
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionLocalCumulativeCutStretch.png</normaloff>:/images/themes/default/mActionLocalCumulativeCutStretch.png</iconset>
</property>
<property name="text">
<string>Local Cumulative Cut Stretch</string>
</property>
<property name="toolTip">
<string>Local cumulative cut stretch using current extent, default limits and estimated values.</string>
</property>
</action>
<action name="mActionFullCumulativeCutStretch">
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionFullCumulativeCutStretch.png</normaloff>:/images/themes/default/mActionFullCumulativeCutStretch.png</iconset>
</property>
<property name="text">
<string>Full Dataset Cumulative Cut Stretch</string>
</property>
<property name="toolTip">
<string>Cumulative cut stretch using full dataset extent, default limits and estimated values.</string>
</property>
</action>
</widget>
<resources>
<include location="../../images/images.qrc"/>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.