10 changes: 6 additions & 4 deletions src/core/raster/qgsrasterinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,14 @@ class CORE_EXPORT QgsRasterInterface

/** Retruns value representing 'no data' (NULL) */
// TODO: Q_DECL_DEPRECATED
virtual double noDataValue() const { return 0; }
//virtual double noDataValue() const { return 0; }

/** Return no data value for specific band. Each band/provider must have
* no data value, if there is no one set in original data, provider decides one
* possibly using wider data type.
* @param bandNo band number
* @return No data value */
virtual double noDataValue( int bandNo ) const { Q_UNUSED( bandNo ); return noDataValue(); }
virtual double noDataValue( int bandNo ) const { Q_UNUSED( bandNo ); return std::numeric_limits<double>::quiet_NaN(); }

/** Test if value is nodata for specific band
* @param bandNo band number
Expand Down Expand Up @@ -216,6 +216,10 @@ class CORE_EXPORT QgsRasterInterface
* returned. */
double time( bool cumulative = false );

inline static double readValue( void *data, QgsRasterInterface::DataType type, int index );

inline static void writeValue( void *data, QgsRasterInterface::DataType type, int index, double value );

/** \brief Print double value with all necessary significant digits.
* It is ensured that conversion back to double gives the same number.
* @param value the value to be printed
Expand All @@ -238,8 +242,6 @@ class CORE_EXPORT QgsRasterInterface
// On/off state, if off, it does not do anything, replicates input
bool mOn;

inline static double readValue( void *data, QgsRasterInterface::DataType type, int index );
inline static void writeValue( void *data, QgsRasterInterface::DataType type, int index, double value );

/** \brief Test if value is within the list of ranges
* @param value value
Expand Down
33 changes: 20 additions & 13 deletions src/core/raster/qgsrasterlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ void QgsRasterLayer::computeMinimumMaximumFromLastExtent( int theBand, double* t
if ( !theMinMax )
return;

int myDataType = mDataProvider->dataType( theBand );
QgsRasterInterface::DataType myDataType = mDataProvider->dataType( theBand );
void* myScanData = readData( theBand, &mLastViewPort );

/* Check for out of memory error */
Expand All @@ -521,8 +521,8 @@ void QgsRasterLayer::computeMinimumMaximumFromLastExtent( int theBand, double* t
{
for ( int myColumn = 0; myColumn < mLastViewPort.drawableAreaXDim; ++myColumn )
{
myValue = readValue( myScanData, myDataType, myRow * mLastViewPort.drawableAreaXDim + myColumn );
if ( mValidNoDataValue && ( qAbs( myValue - mNoDataValue ) <= TINY_VALUE || myValue != myValue ) )
myValue = QgsRasterInterface::readValue( myScanData, myDataType, myRow * mLastViewPort.drawableAreaXDim + myColumn );
if ( mDataProvider->isNoDataValue( theBand, myValue ) )
{
continue;
}
Expand Down Expand Up @@ -1234,9 +1234,10 @@ QString QgsRasterLayer::metadata()
myMetadata += tr( "No Data Value" );
myMetadata += "</p>\n";
myMetadata += "<p>";
if ( mValidNoDataValue )
// TODO: all bands
if ( mDataProvider->srcHasNoDataValue( 1 ) )
{
myMetadata += QString::number( mNoDataValue );
myMetadata += QString::number( mDataProvider->srcNoDataValue( 1 ) );
}
else
{
Expand Down Expand Up @@ -1545,7 +1546,7 @@ double QgsRasterLayer::rasterUnitsPerPixel()
return 1;
}


#if 0
void QgsRasterLayer::resetNoDataValue()
{
mNoDataValue = std::numeric_limits<int>::max();
Expand Down Expand Up @@ -1573,7 +1574,7 @@ void QgsRasterLayer::resetNoDataValue()
mValidNoDataValue = mDataProvider->isNoDataValueValid();
}
}

#endif

void QgsRasterLayer::setBlueBandName( QString const & theBandName )
{
Expand All @@ -1596,8 +1597,8 @@ void QgsRasterLayer::init()
setDrawingStyle( QgsRasterLayer::UndefinedDrawingStyle );

mBandCount = 0;
mNoDataValue = -9999.0;
mValidNoDataValue = false;
//mNoDataValue = -9999.0;
//mValidNoDataValue = false;

//Initialize the last view port structure, should really be a class
mLastViewPort.drawableAreaXDim = 0;
Expand Down Expand Up @@ -1719,7 +1720,7 @@ void QgsRasterLayer::setDataProvider( QString const & provider )
mDataSource = mDataProvider->dataSourceUri();
}

setNoDataValue( mDataProvider->noDataValue() );
//setNoDataValue( mDataProvider->noDataValue() );

// get the extent
QgsRectangle mbr = mDataProvider->extent();
Expand All @@ -1737,7 +1738,7 @@ void QgsRasterLayer::setDataProvider( QString const & provider )
// upper case the first letter of the layer name
QgsDebugMsg( "mLayerName: " + name() );

mValidNoDataValue = mDataProvider->isNoDataValueValid();
//mValidNoDataValue = mDataProvider->isNoDataValueValid();

// set up the raster drawing style
// Do not set any 'sensible' style here, the style is set later
Expand Down Expand Up @@ -2228,6 +2229,7 @@ void QgsRasterLayer::setMinimumValue( QString, double, bool )
//legacy method
}

#if 0
void QgsRasterLayer::setNoDataValue( double theNoDataValue )
{
if ( theNoDataValue != mNoDataValue )
Expand All @@ -2246,6 +2248,7 @@ void QgsRasterLayer::setNoDataValue( double theNoDataValue )
#endif
}
}
#endif

void QgsRasterLayer::setRasterShaderFunction( QgsRasterShaderFunction* )
{
Expand Down Expand Up @@ -2596,7 +2599,7 @@ bool QgsRasterLayer::readXml( const QDomNode& layer_node )
// Load user no data value
QDomElement noDataElement = layer_node.firstChildElement( "noData" );

QDomNodeList noDataBandList = noDataElement.elementsByTagName( "noDataRangeList" );
QDomNodeList noDataBandList = noDataElement.elementsByTagName( "noDataList" );

for ( int i = 0; i < noDataBandList.size(); ++i )
{
Expand All @@ -2606,6 +2609,7 @@ bool QgsRasterLayer::readXml( const QDomNode& layer_node )
QgsDebugMsg( QString( "bandNo = %1" ).arg( bandNo ) );
if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
{
mDataProvider->setUseSrcNoDataValue( bandNo, bandElement.attribute( "useSrcNoData" ).toInt() );
QList<QgsRasterInterface::Range> myNoDataRangeList;

QDomNodeList rangeList = bandElement.elementsByTagName( "noDataRange" );
Expand Down Expand Up @@ -2686,8 +2690,9 @@ bool QgsRasterLayer::writeXml( QDomNode & layer_node,
{
if ( mDataProvider->userNoDataValue( bandNo ).isEmpty() ) continue;

QDomElement noDataRangeList = document.createElement( "noDataRangeList" );
QDomElement noDataRangeList = document.createElement( "noDataList" );
noDataRangeList.setAttribute( "bandNo", bandNo );
noDataRangeList.setAttribute( "useSrcNoData", mDataProvider->useSrcNoDataValue( bandNo ) );

foreach ( QgsRasterInterface::Range range, mDataProvider->userNoDataValue( bandNo ) )
{
Expand Down Expand Up @@ -2816,6 +2821,7 @@ bool QgsRasterLayer::readFile( QString const &theFilename )
/*
* @param index index in memory block
*/
#if 0
double QgsRasterLayer::readValue( void *data, int type, int index )
{
if ( !data )
Expand Down Expand Up @@ -2851,6 +2857,7 @@ double QgsRasterLayer::readValue( void *data, int type, int index )

return mValidNoDataValue ? mNoDataValue : 0.0;
}
#endif

bool QgsRasterLayer::update()
{
Expand Down
14 changes: 7 additions & 7 deletions src/core/raster/qgsrasterlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,10 +342,10 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
int height() { return mHeight; }

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

/** \brief Accessor that returns the NO_DATA entry for this raster */
double noDataValue( bool* isValid = 0 ) { if ( isValid ) { *isValid = mValidNoDataValue;} return mNoDataValue; }
//double noDataValue( bool* isValid = 0 ) { if ( isValid ) { *isValid = mValidNoDataValue;} return mNoDataValue; }

/** \brief Accessor for raster layer type (which is a read only property) */
LayerType rasterType() { return mRasterType; }
Expand Down Expand Up @@ -553,7 +553,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
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 @@ -626,7 +626,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
Q_DECL_DEPRECATED 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 Expand Up @@ -795,7 +795,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer

/** \brief Read a raster value given position from memory block created by readData() */
//inline double readValue( void *data, GDALDataType type, int index );
inline double readValue( void *data, int type, int index );
//inline double readValue( void *data, int type, int index );

/** \brief Update the layer if it is outdated */
bool update();
Expand Down Expand Up @@ -869,7 +869,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
bool mModified;

/** \brief Cell value representing no data. e.g. -9999 */
double mNoDataValue;
//double mNoDataValue;

/** [ data provider interface ] Data provider key */
QString mProviderKey;
Expand All @@ -889,7 +889,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
bool mUserDefinedRGBMinimumMaximum;

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

//QgsRasterRenderer* mRenderer;
//QgsRasterResampleFilter *mResampleFilter;
Expand Down
3 changes: 2 additions & 1 deletion src/core/raster/qgsrasterrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ bool QgsRasterRenderer::usesTransparency( ) const
{
return true;
}
return ( mAlphaBand > 0 || ( mRasterTransparency && !mRasterTransparency->isEmpty( mInput->noDataValue() ) ) || !doubleNear( mOpacity, 1.0 ) );
// TODO: nodata per band
return ( mAlphaBand > 0 || ( mRasterTransparency && !mRasterTransparency->isEmpty( mInput->noDataValue( 1 ) ) ) || !doubleNear( mOpacity, 1.0 ) );
}

void QgsRasterRenderer::setRasterTransparency( QgsRasterTransparency* t )
Expand Down
44 changes: 0 additions & 44 deletions src/core/raster/qgsrasterrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ class CORE_EXPORT QgsRasterRenderer : public QgsRasterInterface
virtual QList<int> usesBands() const { return QList<int>(); }

protected:
inline double readValue( void *data, QgsRasterInterface::DataType type, int index );

/**Write upper class info into rasterrenderer element (called by writeXML method of subclasses)*/
void _writeXML( QDomDocument& doc, QDomElement& rasterRendererElem ) const;
Expand All @@ -101,47 +100,4 @@ class CORE_EXPORT QgsRasterRenderer : public QgsRasterInterface
double mMaxOversampling;
};

inline double QgsRasterRenderer::readValue( void *data, QgsRasterInterface::DataType type, int index )
{
if ( !mInput )
{
return 0;
}

if ( !data )
{
return mInput->noDataValue();
}

switch ( type )
{
case QgsRasterInterface::Byte:
return ( double )(( GByte * )data )[index];
break;
case QgsRasterInterface::UInt16:
return ( double )(( GUInt16 * )data )[index];
break;
case QgsRasterInterface::Int16:
return ( double )(( GInt16 * )data )[index];
break;
case QgsRasterInterface::UInt32:
return ( double )(( GUInt32 * )data )[index];
break;
case QgsRasterInterface::Int32:
return ( double )(( GInt32 * )data )[index];
break;
case QgsRasterInterface::Float32:
return ( double )(( float * )data )[index];
break;
case QgsRasterInterface::Float64:
return ( double )(( double * )data )[index];
break;
default:
//QgsMessageLog::logMessage( tr( "GDAL data type %1 is not supported" ).arg( type ), tr( "Raster" ) );
break;
}

return mInput->noDataValue();
}

#endif // QGSRASTERRENDERER_H
1 change: 1 addition & 0 deletions src/core/raster/qgsrastertransparency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ int QgsRasterTransparency::alphaValue( double theRedValue, double theGreenValue,
return theGlobalTransparency;
}

// TODO: nodata per band
bool QgsRasterTransparency::isEmpty( double nodataValue ) const
{
return (
Expand Down
88 changes: 48 additions & 40 deletions src/providers/gdal/qgsgdalprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,7 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,
}
#endif

#if 0
bool QgsGdalProvider::srcHasNoDataValue( int bandNo ) const
{
if ( mGdalDataset )
Expand All @@ -754,6 +755,7 @@ double QgsGdalProvider::noDataValue() const
}
return std::numeric_limits<int>::max(); // should not happen or be used
}
#endif

void QgsGdalProvider::computeMinMax( int theBandNo )
{
Expand Down Expand Up @@ -834,7 +836,7 @@ QMap<int, void *> QgsGdalProvider::identify( const QgsPoint & point )
for ( int i = 1; i <= GDALGetRasterCount( mGdalDataset ); i++ )
{
void * data = VSIMalloc( dataTypeSize( i ) / 8 );
writeValue( data, dataType( i ), 0, noDataValue() );
writeValue( data, dataType( i ), 0, noDataValue( i ) );
results.insert( i, data );
}
}
Expand Down Expand Up @@ -2127,7 +2129,6 @@ QgsRasterBandStats QgsGdalProvider::bandStatistics( int theBandNo, int theStats,

#ifdef QGISDEBUG
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 @@ -2273,57 +2274,64 @@ void QgsGdalProvider::initBaseDataset()
//
// Determine the nodata value and data type
//
mValidNoDataValue = true;
//mValidNoDataValue = true;
for ( int i = 1; i <= GDALGetRasterCount( mGdalBaseDataset ); i++ )
{
computeMinMax( i );
GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, i );
GDALDataType myGdalDataType = GDALGetRasterDataType( myGdalBand );

int isValid = false;
double myNoDataValue = GDALGetRasterNoDataValue( GDALGetRasterBand( mGdalDataset, i ), &isValid );
double myNoDataValue = GDALGetRasterNoDataValue( myGdalBand, &isValid );
if ( isValid )
{
QgsDebugMsg( QString( "GDALGetRasterNoDataValue = %1" ).arg( myNoDataValue ) ) ;
mGdalDataType.append( myGdalDataType );
mSrcNoDataValue.append( myNoDataValue );
mSrcHasNoDataValue.append( true );
mUseSrcNoDataValue.append( true );
}
else
{
// But we need a null value in case of reprojection and BTW also for
// aligned margines

switch ( srcDataType( i ) )
{
case QgsRasterDataProvider::Byte:
// Use longer data type to avoid conflict with real data
myNoDataValue = -32768.0;
mGdalDataType.append( GDT_Int16 );
break;
case QgsRasterDataProvider::Int16:
myNoDataValue = -2147483648.0;
mGdalDataType.append( GDT_Int32 );
break;
case QgsRasterDataProvider::UInt16:
myNoDataValue = -2147483648.0;
mGdalDataType.append( GDT_Int32 );
break;
case QgsRasterDataProvider::Int32:
myNoDataValue = -2147483648.0;
mGdalDataType.append( myGdalDataType );
break;
case QgsRasterDataProvider::UInt32:
myNoDataValue = 4294967295.0;
mGdalDataType.append( myGdalDataType );
break;
default:
myNoDataValue = std::numeric_limits<int>::max();
// Would NaN work well?
//myNoDataValue = std::numeric_limits<double>::quiet_NaN();
mGdalDataType.append( myGdalDataType );
}
mSrcNoDataValue.append( std::numeric_limits<double>::quiet_NaN() );
mSrcHasNoDataValue.append( false );
mUseSrcNoDataValue.append( false );
}
// It may happen that nodata value given by GDAL is wrong and it has to be
// disabled by user, in that case we need another value to be used for nodata
// (for reprojection for example) -> always internaly represent as wider type
// with mInternalNoDataValue in reserve.
int myInternalGdalDataType = myGdalDataType;
double myInternalNoDataValue = 123;
switch ( srcDataType( i ) )
{
case QgsRasterDataProvider::Byte:
myInternalNoDataValue = -32768.0;
myInternalGdalDataType = GDT_Int16;
break;
case QgsRasterDataProvider::Int16:
myInternalNoDataValue = -2147483648.0;
myInternalGdalDataType = GDT_Int32;
break;
case QgsRasterDataProvider::UInt16:
myInternalNoDataValue = -2147483648.0;
myInternalGdalDataType = GDT_Int32;
break;
case QgsRasterDataProvider::Int32:
// We believe that such values is no used in real data
myInternalNoDataValue = -2147483648.0;
break;
case QgsRasterDataProvider::UInt32:
// We believe that such values is no used in real data
myInternalNoDataValue = 4294967295.0;
break;
default: // Float32, Float64
//myNoDataValue = std::numeric_limits<int>::max();
// NaN should work well
myInternalNoDataValue = std::numeric_limits<double>::quiet_NaN();
}
//mSrcNoDataValue.append( myNoDataValue );
mNoDataValue.append( myNoDataValue );
QgsDebugMsg( QString( "mNoDataValue[%1] = %2" ).arg( i - 1 ).arg( mNoDataValue[i-1] ) );
mGdalDataType.append( myInternalGdalDataType );
mInternalNoDataValue.append( myInternalNoDataValue );
QgsDebugMsg( QString( "mInternalNoDataValue[%1] = %2" ).arg( i - 1 ).arg( mInternalNoDataValue[i-1] ) );
}

mValid = true;
Expand Down
4 changes: 2 additions & 2 deletions src/providers/gdal/qgsgdalprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase

//void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height );

bool srcHasNoDataValue( int bandNo ) const;
double noDataValue() const;
//bool srcHasNoDataValue( int bandNo ) const;
//double noDataValue() const;
void computeMinMax( int bandNo );
double minimumValue( int bandNo ) const;
double maximumValue( int bandNo ) const;
Expand Down
21 changes: 16 additions & 5 deletions src/providers/grass/qgis.d.rast.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#ifdef WIN32
#include <fcntl.h>
#include <io.h>
Expand Down Expand Up @@ -140,6 +141,15 @@ static int cell_draw( char *name,
long one = 1;
FILE *fo;
int raster_size;
#ifdef NAN
double dnul = NAN;
float fnul = NAN;
#else
double dnul = strtod( "NAN", 0 );
float fnul = strtof( "NAN", 0 );
// another possibility would be nan()/nanf() - C99
// and 0./0. if all fails
#endif

big_endian = !( *(( char * )( &one ) ) );

Expand Down Expand Up @@ -213,18 +223,19 @@ static int cell_draw( char *name,
// see comments in QgsGrassRasterProvider::noDataValue()
if ( data_type == CELL_TYPE )
{
int nul = -2000000000;
//int nul = -2000000000;
int nul = -2147483648;
fwrite( &nul , 4, 1, fo );
}
else if ( data_type == DCELL_TYPE )
{
double nul = -1e+300;
fwrite( &nul , 8, 1, fo );
//double nul = -1e+300;
fwrite( &dnul , 8, 1, fo );
}
else if ( data_type == FCELL_TYPE )
{
double nul = -1e+30;
fwrite( &nul , 4, 1, fo );
//double nul = -1e+30;
fwrite( &fnul , 4, 1, fo );
}
}
else
Expand Down
25 changes: 12 additions & 13 deletions src/providers/grass/qgsgrassrasterprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* (at your option) any later version. *
* *
***************************************************************************/

#include <limits>

#include "qgslogger.h"
#include "qgsgrass.h"
Expand Down Expand Up @@ -76,7 +76,7 @@ QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )
mTimestamp = dataTimestamp();

mRasterValue.start( mGisdbase, mLocation, mMapset, mMapName );
mValidNoDataValue = true;
//mValidNoDataValue = true;

mCrs = QgsGrass::crs( mGisdbase, mLocation );
QgsDebugMsg( "mCrs: " + mCrs.toWkt() );
Expand All @@ -92,10 +92,11 @@ QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )

// TODO: avoid showing these strange numbers in GUI
// TODO: don't save no data values in project file, add a flag if value was defined by user

double myInternalNoDataValue;
if ( mGrassDataType == CELL_TYPE )
{
//limit: -2147483647;
mNoDataValue = -2000000000;
myInternalNoDataValue = -2147483648;
}
else if ( mGrassDataType == DCELL_TYPE )
{
Expand All @@ -105,7 +106,8 @@ QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )
// No data value is shown in GUI, use some nice number.
// Choose values with small representation error.
// limit: 1.7976931348623157e+308
mNoDataValue = -1e+300;
//myInternalNoDataValue = -1e+300;
myInternalNoDataValue = std::numeric_limits<double>::quiet_NaN();
}
else
{
Expand All @@ -115,9 +117,11 @@ QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )
}

// limit: 3.40282347e+38
mNoDataValue = -1e+30;
//myInternalNoDataValue = -1e+30;
myInternalNoDataValue = std::numeric_limits<float>::quiet_NaN();
}
QgsDebugMsg( QString( "mNoDataValue = %1" ).arg( mNoDataValue ) );
mInternalNoDataValue.append( myInternalNoDataValue );
QgsDebugMsg( QString( "myInternalNoDataValue = %1" ).arg( myInternalNoDataValue ) );

// TODO: refresh mRows and mCols if raster was rewritten
// We have to decide some reasonable block size, not to big to occupate too much
Expand Down Expand Up @@ -285,11 +289,6 @@ void QgsGrassRasterProvider::readBlock( int bandNo, QgsRectangle const & viewEx
memcpy( block, data.data(), size );
}

double QgsGrassRasterProvider::noDataValue() const
{
return mNoDataValue;
}

double QgsGrassRasterProvider::minimumValue( int bandNo ) const
{
Q_UNUSED( bandNo );
Expand Down Expand Up @@ -428,7 +427,7 @@ QMap<int, void *> QgsGrassRasterProvider::identify( const QgsPoint & thePoint )
QString strValue = mRasterValue.value( thePoint.x(), thePoint.y() );
// attention, value tool does his own tricks with grass identify() so it stops to refresh values outside extent or null values e.g.

double value = noDataValue();
double value = noDataValue( 1 );

if ( strValue != "out" && strValue != "null" )
{
Expand Down
4 changes: 2 additions & 2 deletions src/providers/grass/qgsgrassrasterprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class QgsGrassRasterProvider : public QgsRasterDataProvider
void readBlock( int bandNo, int xBlock, int yBlock, void *data );
void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data );

double noDataValue() const;
//double noDataValue() const;
double minimumValue( int bandNo )const;
double maximumValue( int bandNo )const;

Expand Down Expand Up @@ -263,7 +263,7 @@ class QgsGrassRasterProvider : public QgsRasterDataProvider

QgsGrassRasterValue mRasterValue;

double mNoDataValue;
//double mNoDataValue;
};

#endif
97 changes: 46 additions & 51 deletions src/providers/wcs/qgswcsprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,68 +280,72 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )

QgsDebugMsg( QString( "myGdalDataType[%1] = %2" ).arg( i - 1 ).arg( myGdalDataType ) );
mSrcGdalDataType.append( myGdalDataType );
// TODO: This could be shared with GDAL provider
int isValid = false;

// UMN Mapserver does not automaticaly set null value, METADATA wcs_rangeset_nullvalue must be used
// http://lists.osgeo.org/pipermail/mapserver-users/2010-April/065328.html

// TODO:

// TODO: This could be shared with GDAL provider
int isValid = false;
double myNoDataValue = GDALGetRasterNoDataValue( gdalBand, &isValid );
if ( isValid )
{
QgsDebugMsg( QString( "GDALGetRasterNoDataValue = %1" ).arg( myNoDataValue ) ) ;
mGdalDataType.append( myGdalDataType );
mSrcNoDataValue.append( myNoDataValue );
mSrcHasNoDataValue.append( true );
mUseSrcNoDataValue.append( true );
}
else
{
// But we need a null value in case of reprojection and BTW also for
// aligned margines
switch ( dataTypeFromGdal( myGdalDataType ) )
{

case QgsRasterDataProvider::Byte:
// Use longer data type to avoid conflict with real data
myNoDataValue = -32768.0;
mGdalDataType.append( GDT_Int16 );
break;
case QgsRasterDataProvider::Int16:
myNoDataValue = -2147483648.0;
mGdalDataType.append( GDT_Int32 );
break;
case QgsRasterDataProvider::UInt16:
myNoDataValue = -2147483648.0;
mGdalDataType.append( GDT_Int32 );
break;
case QgsRasterDataProvider::Int32:
myNoDataValue = -2147483648.0;
mGdalDataType.append( myGdalDataType );
break;
case QgsRasterDataProvider::UInt32:
myNoDataValue = 4294967295.0;
mGdalDataType.append( myGdalDataType );
break;
default:
myNoDataValue = std::numeric_limits<int>::max();
// Would NaN work well?
//myNoDataValue = std::numeric_limits<double>::quiet_NaN();
mGdalDataType.append( myGdalDataType );
}
mSrcNoDataValue.append( std::numeric_limits<double>::quiet_NaN() );
mSrcHasNoDataValue.append( false );
mUseSrcNoDataValue.append( false );
}
mNoDataValue.append( myNoDataValue );
// It may happen that nodata value given by GDAL is wrong and it has to be
// disabled by user, in that case we need another value to be used for nodata
// (for reprojection for example) -> always internaly represent as wider type
// with mInternalNoDataValue in reserve.
int myInternalGdalDataType = myGdalDataType;
double myInternalNoDataValue;
switch ( srcDataType( i ) )
{
case QgsRasterDataProvider::Byte:
myInternalNoDataValue = -32768.0;
myInternalGdalDataType = GDT_Int16;
break;
case QgsRasterDataProvider::Int16:
myInternalNoDataValue = -2147483648.0;
myInternalGdalDataType = GDT_Int32;
break;
case QgsRasterDataProvider::UInt16:
myInternalNoDataValue = -2147483648.0;
myInternalGdalDataType = GDT_Int32;
break;
case QgsRasterDataProvider::Int32:
// We believe that such values is no used in real data
myInternalNoDataValue = -2147483648.0;
break;
case QgsRasterDataProvider::UInt32:
// We believe that such values is no used in real data
myInternalNoDataValue = 4294967295.0;
break;
default: // Float32, Float64
//myNoDataValue = std::numeric_limits<int>::max();
// NaN should work well
myInternalNoDataValue = std::numeric_limits<double>::quiet_NaN();
}
mGdalDataType.append( myInternalGdalDataType );
mInternalNoDataValue.append( myInternalNoDataValue );
QgsDebugMsg( QString( "mInternalNoDataValue[%1] = %2" ).arg( i - 1 ).arg( mInternalNoDataValue[i-1] ) );

// TODO: what to do if null values from DescribeCoverage differ?
if ( !mCoverageSummary.nullValues.contains( myNoDataValue ) )
{
QgsDebugMsg( QString( "noDataValue %1 is missing in nullValues from CoverageDescription" ).arg( myNoDataValue ) );
}

mValidNoDataValue = true;

QgsDebugMsg( QString( "mSrcGdalDataType[%1] = %2" ).arg( i - 1 ).arg( mSrcGdalDataType[i-1] ) );
QgsDebugMsg( QString( "mGdalDataType[%1] = %2" ).arg( i - 1 ).arg( mGdalDataType[i-1] ) );
QgsDebugMsg( QString( "mNoDataValue[%1] = %2" ).arg( i - 1 ).arg( mNoDataValue[i-1] ) );
QgsDebugMsg( QString( "mSrcNoDataValue[%1] = %2" ).arg( i - 1 ).arg( mSrcNoDataValue[i-1] ) );

// Create and store color table
// TODO: never tested because mapserver (6.0.3) does not support color tables
Expand Down Expand Up @@ -1074,15 +1078,6 @@ int QgsWcsProvider::bandCount() const
return mBandCount;
}

double QgsWcsProvider::noDataValue() const
{
if ( mNoDataValue.size() > 0 )
{
return mNoDataValue[0];
}
return std::numeric_limits<int>::max(); // should not happen or be used
}

// this is only called once when statistics are calculated
// TODO
int QgsWcsProvider::xBlockSize() const
Expand Down Expand Up @@ -1525,7 +1520,7 @@ QMap<int, void *> QgsWcsProvider::identify( const QgsPoint & thePoint )
for ( int i = 1; i <= bandCount(); i++ )
{
void * data = VSIMalloc( dataTypeSize( i ) / 8 );
writeValue( data, dataType( i ), 0, noDataValue() );
writeValue( data, dataType( i ), 0, noDataValue( i ) );
results.insert( i, data );
}
return results;
Expand Down
4 changes: 2 additions & 2 deletions src/providers/wcs/qgswcsprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
QgsRasterInterface::DataType dataType( int bandNo ) const;
QgsRasterInterface::DataType srcDataType( int bandNo ) const;
int bandCount() const;
double noDataValue() const;
//double noDataValue() const;
int xBlockSize() const;
int yBlockSize() const;
int xSize() const;
Expand Down Expand Up @@ -303,7 +303,7 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
QList<int>mSrcGdalDataType;

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

/** Color tables indexed from 0 */
QList< QList<QgsColorRampShader::ColorRampItem> > mColorTables;
Expand Down
7 changes: 5 additions & 2 deletions src/ui/qgsrasterlayerpropertiesbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -439,9 +439,12 @@
<number>1</number>
</property>
<item>
<widget class="QLabel" name="lblSrcNoDataValueLabel">
<widget class="QCheckBox" name="mSrcNoDataValueCheckBox">
<property name="toolTip">
<string>Use original source no data value.</string>
</property>
<property name="text">
<string>Source no data value:</string>
<string>No data value:</string>
</property>
</widget>
</item>
Expand Down
2 changes: 1 addition & 1 deletion tests/src/core/testqgsrasterfilewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ bool TestQgsRasterFileWriter::writeTest( QString theRasterName )
// All OK, we can delete the file
tmpFile.setAutoRemove( ok );

return true;
return ok;
}

void TestQgsRasterFileWriter::log( QString msg )
Expand Down