Skip to content

Commit

Permalink
Merge branch 'master' of github.com:qgis/Quantum-GIS
Browse files Browse the repository at this point in the history
  • Loading branch information
timlinux committed Sep 20, 2012
2 parents 8fd7805 + b1e00e9 commit ad78d7b
Show file tree
Hide file tree
Showing 29 changed files with 528 additions and 322 deletions.
2 changes: 1 addition & 1 deletion python/core/qgsrasterinterface.sip
Expand Up @@ -82,7 +82,7 @@ class QgsRasterInterface

virtual int bandCount() const;

virtual double noDataValue() const;
virtual double noDataValue( int bandNo ) const;

virtual void * block( int bandNo, const QgsRectangle & extent, int width, int height );

Expand Down
8 changes: 4 additions & 4 deletions python/core/qgsrasterlayer.sip
Expand Up @@ -172,7 +172,7 @@ public:
int height();

/** \brief Is the NoDataValue Valid */
bool isNoDataValueValid() const;
//bool isNoDataValueValid() const;

/** \brief Accessor for mGrayMinimumMaximumEstimated */
//bool isGrayMinimumMaximumEstimated() const; //removed with raster redesign
Expand All @@ -181,7 +181,7 @@ public:
//bool isRGBMinimumMaximumEstimated() const; //removed with raster redesign

/** \brief Accessor that returns the NO_DATA entry for this raster */
double noDataValue( bool* isValid = 0 );
//double noDataValue( bool* isValid = 0 );

/** \brief Returns a pointer to the transparency object */
//QgsRasterTransparency* rasterTransparency(); //removed with raster redesign
Expand Down Expand Up @@ -385,7 +385,7 @@ public:
//bool readColorTable( int theBandNumber, QList<QgsColorRampShader::ColorRampItem>* theList );

/** \brief Simple reset function that set the noDataValue back to the value stored in the first raster band */
void resetNoDataValue();
//void resetNoDataValue();

/** \brief Mutator for blue band name mapping */
void setBlueBandName( const QString & theBandName );
Expand Down Expand Up @@ -431,7 +431,7 @@ public:
void setMinimumValue( QString theBand, double theValue, bool theGenerateLookupTableFlag = true );

/** \brief Mutator that allows the NO_DATA entry for this raster to be overridden */
void setNoDataValue( double theNoData );
//void setNoDataValue( double theNoData );

/** \brief Set the raster shader function to a user defined function
\note ownership of the shader function is transfered to raster shader */
Expand Down
25 changes: 16 additions & 9 deletions src/app/qgsrasterlayerproperties.cpp
Expand Up @@ -546,13 +546,20 @@ void QgsRasterLayerProperties::sync()
// TODO: no data ranges
if ( mRasterLayer->dataProvider()->srcHasNoDataValue( 1 ) )
{
lblSrcNoDataValue->setText( QgsRasterInterface::printValue( mRasterLayer->dataProvider()->noDataValue( 1 ) ) );
lblSrcNoDataValue->setText( QgsRasterInterface::printValue( mRasterLayer->dataProvider()->srcNoDataValue( 1 ) ) );
}
else
{
lblSrcNoDataValue->setText( tr( "not defined" ) );
}

mSrcNoDataValueCheckBox->setChecked( mRasterLayer->dataProvider()->useSrcNoDataValue( 1 ) );

bool enableSrcNoData = mRasterLayer->dataProvider()->srcHasNoDataValue( 1 ) && !qIsNaN( mRasterLayer->dataProvider()->srcNoDataValue( 1 ) );

mSrcNoDataValueCheckBox->setEnabled( enableSrcNoData );
lblSrcNoDataValue->setEnabled( enableSrcNoData );

QList<QgsRasterInterface::Range> noDataRangeList = mRasterLayer->dataProvider()->userNoDataValue( 1 );
QgsDebugMsg( QString( "noDataRangeList.size = %1" ).arg( noDataRangeList.size() ) );
if ( noDataRangeList.size() > 0 )
Expand Down Expand Up @@ -600,13 +607,14 @@ void QgsRasterLayerProperties::sync()
}
else
{
if ( mRasterLayer->isNoDataValueValid() )
// TODO: all bands
if ( mRasterLayer->dataProvider()->srcHasNoDataValue( 1 ) )
{
lblNoData->setText( tr( "No-Data Value: %1" ).arg( mRasterLayer->noDataValue() ) );
lblNoData->setText( tr( "No-Data Value: %1" ).arg( mRasterLayer->dataProvider()->noDataValue( 1 ) ) );
}
else
{
lblNoData->setText( tr( "No-Data Value: Not Set" ) );
lblNoData->setText( tr( "No-Data Value: " ) + tr( "n/a" ) );
}
}

Expand Down Expand Up @@ -678,6 +686,7 @@ void QgsRasterLayerProperties::apply()
for ( int bandNo = 1; bandNo <= mRasterLayer->dataProvider()->bandCount(); bandNo++ )
{
mRasterLayer->dataProvider()->setUserNoDataValue( bandNo, myNoDataRangeList );
mRasterLayer->dataProvider()->setUseSrcNoDataValue( bandNo, mSrcNoDataValueCheckBox->isChecked() );
}

//set renderer from widget
Expand Down Expand Up @@ -992,32 +1001,30 @@ void QgsRasterLayerProperties::on_pbnDefaultValues_clicked()

setupTransparencyTable( nBands );

// I don't think that noDataValue should be added to transparency list
#if 0
if ( nBands == 3 )
{
if ( mRasterLayer->isNoDataValueValid() )
{
// I don't think that noDataValue should be added to transparency list
#if 0
tableTransparency->insertRow( tableTransparency->rowCount() );
setTransparencyCell( 0, 0, mRasterLayer->noDataValue() );
setTransparencyCell( 0, 1, mRasterLayer->noDataValue() );
setTransparencyCell( 0, 2, mRasterLayer->noDataValue() );
setTransparencyCell( 0, 1, 100 );
#endif
}
}
else //1 band
{
if ( mRasterLayer->isNoDataValueValid() )
{
#if 0
tableTransparency->insertRow( tableTransparency->rowCount() );
setTransparencyCell( 0, 0, mRasterLayer->noDataValue() );
setTransparencyCell( 0, 1, mRasterLayer->noDataValue() );
setTransparencyCell( 0, 1, 100 );
#endif
}
}
#endif

tableTransparency->resizeColumnsToContents(); // works only with values
tableTransparency->resizeRowsToContents();
Expand Down
36 changes: 28 additions & 8 deletions src/core/qgsrasterdataprovider.cpp
Expand Up @@ -25,6 +25,27 @@

#include <qmath.h>

void QgsRasterDataProvider::setUseSrcNoDataValue( int bandNo, bool use )
{
if ( mUseSrcNoDataValue.size() < bandNo )
{
for ( int i = mUseSrcNoDataValue.size(); i < bandNo; i++ )
{
mUseSrcNoDataValue.append( false );
}
}
mUseSrcNoDataValue[bandNo-1] = use;
}

double QgsRasterDataProvider::noDataValue( int bandNo ) const
{
if ( mSrcHasNoDataValue.value( bandNo - 1 ) && mUseSrcNoDataValue.value( bandNo - 1 ) )
{
return mSrcNoDataValue.value( bandNo -1 );
}
return mInternalNoDataValue.value( bandNo -1 );
}

void QgsRasterDataProvider::readBlock( int bandNo, QgsRectangle
const & viewExtent, int width,
int height,
Expand Down Expand Up @@ -289,7 +310,7 @@ QByteArray QgsRasterDataProvider::noValueBytes( int theBandNo )
QByteArray ba;
ba.resize(( int )size );
char * data = ba.data();
double noval = mNoDataValue[theBandNo-1];
double noval = noDataValue( theBandNo - 1 );
unsigned char uc;
unsigned short us;
short s;
Expand Down Expand Up @@ -616,7 +637,6 @@ QgsRasterBandStats QgsRasterDataProvider::bandStatistics( int theBandNo,
int myWidth = myRasterBandStats.width;
int myHeight = myRasterBandStats.height;

double myNoDataValue = noDataValue();
int myDataType = dataType( theBandNo );

int myXBlockSize = xBlockSize();
Expand Down Expand Up @@ -669,7 +689,8 @@ QgsRasterBandStats QgsRasterDataProvider::bandStatistics( int theBandNo,
double myValue = readValue( myData, myDataType, myX + ( myY * myBlockWidth ) );
//QgsDebugMsg ( QString ( "%1 %2 value %3" ).arg (myX).arg(myY).arg( myValue ) );

if ( mValidNoDataValue && ( qAbs( myValue - myNoDataValue ) <= TINY_VALUE ) )
// TODO: user nodata
if ( isNoDataValue( theBandNo, myValue ) )
{
continue; // NULL
}
Expand Down Expand Up @@ -718,7 +739,6 @@ QgsRasterBandStats QgsRasterDataProvider::bandStatistics( int theBandNo,
myRasterBandStats.stdDev = sqrt( mySumOfSquares / ( myRasterBandStats.elementCount - 1 ) );

QgsDebugMsg( "************ STATS **************" );
QgsDebugMsg( QString( "VALID NODATA %1" ).arg( mValidNoDataValue ) );
QgsDebugMsg( QString( "MIN %1" ).arg( myRasterBandStats.minimumValue ) );
QgsDebugMsg( QString( "MAX %1" ).arg( myRasterBandStats.maximumValue ) );
QgsDebugMsg( QString( "RANGE %1" ).arg( myRasterBandStats.range ) );
Expand Down Expand Up @@ -893,7 +913,6 @@ QgsRasterHistogram QgsRasterDataProvider::histogram( int theBandNo,
QgsRectangle myExtent = myHistogram.extent;
myHistogram.histogramVector.resize( myBinCount );

double myNoDataValue = noDataValue();
int myDataType = dataType( theBandNo );

int myXBlockSize = xBlockSize();
Expand Down Expand Up @@ -953,7 +972,8 @@ QgsRasterHistogram QgsRasterDataProvider::histogram( int theBandNo,
double myValue = readValue( myData, myDataType, myX + ( myY * myBlockWidth ) );
//QgsDebugMsg ( QString ( "%1 %2 value %3" ).arg (myX).arg(myY).arg( myValue ) );

if ( mValidNoDataValue && ( qAbs( myValue - myNoDataValue ) <= TINY_VALUE ) )
// TODO: user defined nodata values
if ( isNoDataValue( theBandNo, myValue ) )
{
continue; // NULL
}
Expand Down Expand Up @@ -1034,7 +1054,7 @@ void QgsRasterDataProvider::cumulativeCut( int theBandNo,
double QgsRasterDataProvider::readValue( void *data, int type, int index )
{
if ( !data )
return mValidNoDataValue ? noDataValue() : 0.0;
return std::numeric_limits<double>::quiet_NaN();

switch ( type )
{
Expand Down Expand Up @@ -1063,7 +1083,7 @@ double QgsRasterDataProvider::readValue( void *data, int type, int index )
QgsLogger::warning( "GDAL data type is not supported" );
}

return mValidNoDataValue ? noDataValue() : 0.0;
return std::numeric_limits<double>::quiet_NaN();
}

void QgsRasterDataProvider::setUserNoDataValue( int bandNo, QList<QgsRasterInterface::Range> noData )
Expand Down
51 changes: 33 additions & 18 deletions src/core/qgsrasterdataprovider.h
Expand Up @@ -295,17 +295,24 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
virtual double readValue( void *data, int type, int index );

/* Return true if source band has no data value */
virtual bool srcHasNoDataValue( int bandNo ) const { Q_UNUSED( bandNo ); return false; }
virtual bool srcHasNoDataValue( int bandNo ) const { return mSrcHasNoDataValue.value( bandNo -1 ); }

/** \brief Get source nodata value usage */
virtual bool useSrcNoDataValue( int bandNo ) const { return mUseSrcNoDataValue.value( bandNo -1 ); }

/** \brief Set source nodata value usage */
virtual void setUseSrcNoDataValue( int bandNo, bool use );

/** value representing null data */
virtual double noDataValue() const { return 0; }
//virtual double noDataValue() const { return 0; }

/** Value representing original source no data. This value my differ from
* if it was overwritten by user */
virtual double noDataValue( int bandNo ) const { return mNoDataValue.value( bandNo -1 ); }
/** Value representing currentno data.
* WARNING: this value returned by this method is not constant. It may change
* for example if user disable use of source no data value. */
virtual double noDataValue( int bandNo ) const;

/** Value representing no data value. */
//virtual double srcNoDataValue( int bandNo ) const { return mSrcNoDataValue.value(bandNo-1); }
virtual double srcNoDataValue( int bandNo ) const { return mSrcNoDataValue.value( bandNo -1 ); }

virtual void setUserNoDataValue( int bandNo, QList<QgsRasterInterface::Range> noData );

Expand Down Expand Up @@ -523,7 +530,7 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
void setDpi( int dpi ) {mDpi = dpi;}

/** \brief Is the NoDataValue Valid */
bool isNoDataValueValid() const { return mValidNoDataValue; }
//bool isNoDataValueValid() const { return mValidNoDataValue; }

static QStringList cStringList2Q_( char ** stringList );

Expand Down Expand Up @@ -603,19 +610,27 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
int mDpi;

/** \brief Cell value representing original source no data. e.g. -9999, indexed from 0 */
//QList<double> mSrcNoDataValue;

/** \brief Cell value representing no data. e.g. -9999, indexed from 0.
* Currently the values is the same as in mSrcNoDataValue, but a possibility
* to overwrite/disable original no data value could be added (?), in that
* case this value would be different. But original source no data value
* cannot be disabled without add additional user nodata (there would not be
* any guaranteed free nodata value available (to represent nodata in
* reprojection for example) */
QList<double> mNoDataValue;
QList<double> mSrcNoDataValue;

/** \brief Source nodata value exist */
QList<bool> mSrcHasNoDataValue;

/** \brief Use source nodata value. User can disable usage of source nodata
* value as nodata. It may happen that a value is wrongly given by GDAL
* as nodata (e.g. 0) and it has to be treated as regular value. */
QList<bool> mUseSrcNoDataValue;

/** \brief Internal value representing nodata. Indexed from 0.
* This values is used to represent nodata if no source nodata is available
* or if the source nodata use was disabled.
* It would be also possible to use wider type only if nodata is really necessary
* in following interfaces, but that could make difficult to subclass
* QgsRasterInterface.
*/
QList<double> mInternalNoDataValue;

/** \brief Flag indicating if the nodatavalue is valid*/
bool mValidNoDataValue;
//bool mValidNoDataValue;

/** \brief List of lists of user defined additional no data values
* for each band, indexed from 0 */
Expand Down
3 changes: 2 additions & 1 deletion src/core/raster/qgsrasterchecker.cpp
Expand Up @@ -75,7 +75,6 @@ bool QgsRasterChecker::runTest( QString theVerifiedKey, QString theVerifiedUri,

if ( verifiedProvider->extent() != expectedProvider->extent() ) ok = false;

compare( "No data (NULL) value", verifiedProvider->noDataValue(), expectedProvider->noDataValue(), mReport, ok );

mReport += "</table>\n";

Expand All @@ -94,6 +93,8 @@ bool QgsRasterChecker::runTest( QString theVerifiedKey, QString theVerifiedUri,
compare( "Source data type", verifiedProvider->srcDataType( band ), expectedProvider->srcDataType( band ), mReport, typesOk );
compare( "Data type", verifiedProvider->dataType( band ), expectedProvider->dataType( band ), mReport, typesOk ) ;

compare( "No data (NULL) value", verifiedProvider->noDataValue( band ), expectedProvider->noDataValue( band ), mReport, typesOk );

bool statsOk = true;
QgsRasterBandStats verifiedStats = verifiedProvider->bandStatistics( band );
QgsRasterBandStats expectedStats = expectedProvider->bandStatistics( band );
Expand Down
14 changes: 8 additions & 6 deletions src/core/raster/qgsrasterfilewriter.cpp
Expand Up @@ -167,14 +167,15 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
bool srcHasNoDataValue = srcProvider->srcHasNoDataValue( bandNo );
bool destHasNoDataValue = false;
double destNoDataValue;
//QgsRasterInterface::DataType destDataType = srcProvider->srcDataType( bandNo );
QgsRasterInterface::DataType destDataType = srcProvider->dataType( bandNo );
QgsRasterInterface::DataType destDataType = srcProvider->srcDataType( bandNo );
//QgsRasterInterface::DataType destDataType = srcProvider->dataType( bandNo );
// TODO: verify what happens/should happen if srcNoDataValue is disabled by setUseSrcNoDataValue
QgsDebugMsg( QString( "srcHasNoDataValue = %1 srcNoDataValue = %2" ).arg( srcHasNoDataValue ).arg( srcProvider->srcNoDataValue( bandNo ) ) );
if ( srcHasNoDataValue )
{

// If source has no data value, it is used by provider
// TODO: this is not realy source no data, we would need srcNoDataValue() but it
// can be safely used I think
destNoDataValue = srcProvider->noDataValue();
destNoDataValue = srcProvider->srcNoDataValue( bandNo );
destHasNoDataValue = true;
}
else if ( nuller && nuller->noData().size() > 0 )
Expand Down Expand Up @@ -255,6 +256,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
destDataTypeList.replace( i, destDataType );
destNoDataValueList.replace( i, destNoDataValue );
}
destDataType = destDataTypeList.value( 0 );

// Try again
destProvider = initOutput( nCols, nRows, crs, geoTransform, nBands, destDataType );
Expand Down Expand Up @@ -367,7 +369,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
else
{
// TODO: this conversion should go to QgsRasterDataProvider::write with additional input data type param
void *destData = QgsRasterInterface::convert( dataList[i-1], srcProvider->srcDataType( i ), destDataType, iterCols * iterRows );
void *destData = QgsRasterInterface::convert( dataList[i-1], srcProvider->dataType( i ), destDataType, iterCols * iterRows );
destDataList.push_back( destData );
CPLFree( dataList[i-1] );
}
Expand Down
2 changes: 2 additions & 0 deletions src/core/raster/qgsrasterinterface.cpp
Expand Up @@ -259,6 +259,8 @@ void * QgsRasterInterface::convert( void *srcData, QgsRasterInterface::DataType
{
double value = readValue( srcData, srcDataType, i );
writeValue( destData, destDataType, i, value );
//double newValue = readValue( destData, destDataType, i );
//QgsDebugMsg( QString("convert type %1 to %2: %3 -> %4").arg(srcDataType).arg(destDataType).arg( value ).arg( newValue ) );
}
return destData;
}

0 comments on commit ad78d7b

Please sign in to comment.