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
etiennesky committed Aug 23, 2012
2 parents 523b56f + 8015c12 commit 13a790d
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 39 deletions.
21 changes: 16 additions & 5 deletions src/app/qgsrasterlayerproperties.cpp
Expand Up @@ -1298,9 +1298,9 @@ void QgsRasterLayerProperties::pixelSelected( const QgsPoint& canvasPoint )
mRasterLayer->identify( mMapCanvas->mapRenderer()->mapToLayerCoordinates( mRasterLayer, canvasPoint ), myPixelMap );

QList<int> bands = renderer->usesBands();
tableTransparency->insertRow( tableTransparency->rowCount() );
setTransparencyCell( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, 100 );
delete renderer;

QList<double> values;
for ( int i = 0; i < bands.size(); ++i )
{
QMap< int, QString >::const_iterator pixelResult = myPixelMap.find( bands.at( i ) );
Expand All @@ -1309,20 +1309,31 @@ void QgsRasterLayerProperties::pixelSelected( const QgsPoint& canvasPoint )
QString value = pixelResult.value();
if ( value != tr( "out of extent" ) )
{
setTransparencyCell( tableTransparency->rowCount() - 1, i, value.toDouble() );
QgsDebugMsg( QString( "Is it %1 of band %2 nodata?" ).arg( value ).arg( bands.at( i ) ) );
if ( value == tr( "null (no data)" ) || // Very bad! TODO: improve identify
mRasterLayer->dataProvider()->isNoDataValue( bands.at( i ), value.toDouble() ) )
{
return; // Dont add nodata, transparent anyway
}
values.append( value.toDouble() );
}
}
}
if ( bands.size() == 1 )
{
// Set 'to'
setTransparencyCell( tableTransparency->rowCount() - 1, 1, transparencyCellValue( tableTransparency->rowCount() - 1, 0 ) );
values.insert( 1, values.value( 0 ) );
}
tableTransparency->insertRow( tableTransparency->rowCount() );
for ( int i = 0; i < values.size(); i++ )
{
setTransparencyCell( tableTransparency->rowCount() - 1, i, values.value( i ) );
}
setTransparencyCell( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, 100 );
}

tableTransparency->resizeColumnsToContents();
tableTransparency->resizeRowsToContents();
delete renderer;
}

void QgsRasterLayerProperties::sliderTransparency_valueChanged( int theValue )
Expand Down
22 changes: 21 additions & 1 deletion src/core/raster/qgsmultibandcolorrenderer.cpp
Expand Up @@ -234,22 +234,42 @@ void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & e
redVal = readValue( redData, redType, currentRasterPos );
greenVal = readValue( greenData, greenType, currentRasterPos );
blueVal = readValue( blueData, blueType, currentRasterPos );
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
if ( mInput->isNoDataValue( mRedBand, redVal ) ||
mInput->isNoDataValue( mGreenBand, greenVal ) ||
mInput->isNoDataValue( mBlueBand, blueVal ) )
{
imageScanLine[j] = defaultColor;
}
else
{
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
}

++currentRasterPos;
continue;
}

bool isNoData = false;
if ( mRedBand > 0 )
{
redVal = readValue( redData, redType, currentRasterPos );
if ( mInput->isNoDataValue( mRedBand, redVal ) ) isNoData = true;
}
if ( mGreenBand > 0 )
{
greenVal = readValue( greenData, greenType, currentRasterPos );
if ( mInput->isNoDataValue( mGreenBand, greenVal ) ) isNoData = true;
}
if ( mBlueBand > 0 )
{
blueVal = readValue( blueData, blueType, currentRasterPos );
if ( mInput->isNoDataValue( mBlueBand, blueVal ) ) isNoData = true;
}
if ( isNoData )
{
imageScanLine[j] = defaultColor;
++currentRasterPos;
continue;
}

//apply default color if red, green or blue not in displayable range
Expand Down
7 changes: 7 additions & 0 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Expand Up @@ -93,6 +93,7 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e
{
return 0;
}
QRgb myDefaultColor = qRgba( 0, 0, 0, 0 );

QgsRasterInterface::DataType transparencyType = QgsRasterInterface::UnknownDataType;
if ( mAlphaBand > 0 )
Expand Down Expand Up @@ -129,6 +130,12 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e
for ( int j = 0; j < width; ++j )
{
val = readValue( rasterData, rasterType, currentRasterPos );
if ( mInput->isNoDataValue( mBandNumber, val ) )
{
imageScanLine[j] = myDefaultColor;
++currentRasterPos;
continue;
}
if ( !hasTransparency )
{
imageScanLine[j] = mColors[ val ].rgba();
Expand Down
12 changes: 12 additions & 0 deletions src/core/raster/qgsrasterinterface.cpp
Expand Up @@ -120,6 +120,18 @@ QgsRasterInterface::DataType QgsRasterInterface::typeWithNoDataValue( DataType d
return newDataType;
}

inline bool QgsRasterInterface::isNoDataValue( int bandNo, double value ) const
{
// More precise would be qIsNaN(value) && qIsNaN(noDataValue(bandNo)), but probably
// not important and slower
if ( qIsNaN( value ) ||
doubleNear( value, noDataValue( bandNo ) ) )
{
return true;
}
return false;
}

// To give to an image preallocated memory is the only way to avoid memcpy
// when we want to keep data but delete QImage
QImage * QgsRasterInterface::createImage( int width, int height, QImage::Format format )
Expand Down
14 changes: 14 additions & 0 deletions src/core/raster/qgsrasterinterface.h
Expand Up @@ -125,8 +125,22 @@ class CORE_EXPORT QgsRasterInterface
}

/** Retruns value representing 'no data' (NULL) */
// TODO: Q_DECL_DEPRECATED
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(); }

/** Test if value is nodata for specific band
* @param bandNo band number
* @param value tested value
* @return true if value is nodata */
virtual bool isNoDataValue( int bandNo, double value ) const ;

/** Read block of data using given extent and size.
* Returns pointer to data.
* Caller is responsible to free the memory returned.
Expand Down
12 changes: 9 additions & 3 deletions src/core/raster/qgsrastertransparency.cpp
Expand Up @@ -178,11 +178,17 @@ bool QgsRasterTransparency::isEmpty( double nodataValue ) const
{
return (
( mTransparentSingleValuePixelList.isEmpty() ||
( mTransparentSingleValuePixelList.size() == 1 && doubleNear( mTransparentSingleValuePixelList.at( 0 ).min, nodataValue ) && doubleNear( mTransparentSingleValuePixelList.at( 0 ).max, nodataValue ) ) )
( mTransparentSingleValuePixelList.size() == 1 &&
( doubleNear( mTransparentSingleValuePixelList.at( 0 ).min, nodataValue ) ||
doubleNear( mTransparentSingleValuePixelList.at( 0 ).max, nodataValue ) ||
( nodataValue > mTransparentSingleValuePixelList.at( 0 ).min &&
nodataValue < mTransparentSingleValuePixelList.at( 0 ).max ) ) ) )
&&
( mTransparentThreeValuePixelList.isEmpty() ||
( mTransparentThreeValuePixelList.size() < 4 && doubleNear( mTransparentThreeValuePixelList.at( 0 ).red, nodataValue ) &&
doubleNear( mTransparentThreeValuePixelList.at( 0 ).green, nodataValue ) && doubleNear( mTransparentThreeValuePixelList.at( 0 ).blue, nodataValue ) ) ) );
( mTransparentThreeValuePixelList.size() == 1 &&
doubleNear( mTransparentThreeValuePixelList.at( 0 ).red, nodataValue ) &&
doubleNear( mTransparentThreeValuePixelList.at( 0 ).green, nodataValue ) &&
doubleNear( mTransparentThreeValuePixelList.at( 0 ).blue, nodataValue ) ) ) );
}

void QgsRasterTransparency::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
Expand Down
7 changes: 7 additions & 0 deletions src/core/raster/qgssinglebandgrayrenderer.cpp
Expand Up @@ -118,6 +118,13 @@ void * QgsSingleBandGrayRenderer::readBlock( int bandNo, QgsRectangle const & e
{
grayVal = readValue( rasterData, rasterType, currentRasterPos );

if ( mInput->isNoDataValue( mGrayBand, grayVal ) )
{
imageScanLine[j] = myDefaultColor;
++currentRasterPos;
continue;
}

//alpha
currentAlpha = mOpacity;
if ( mRasterTransparency )
Expand Down
6 changes: 6 additions & 0 deletions src/core/raster/qgssinglebandpseudocolorrenderer.cpp
Expand Up @@ -117,6 +117,12 @@ void * QgsSingleBandPseudoColorRenderer::readBlock( int bandNo, QgsRectangle co
for ( int j = 0; j < width; ++j )
{
val = readValue( rasterData, rasterType, currentRasterPos );
if ( mInput->isNoDataValue( mBand, val ) )
{
imageScanLine[j] = myDefaultColor;
++currentRasterPos;
continue;
}
if ( !mShader->shade( val, &red, &green, &blue ) )
{
imageScanLine[j] = myDefaultColor;
Expand Down
60 changes: 30 additions & 30 deletions src/providers/grass/qgsgrassrasterprovider.cpp
Expand Up @@ -90,6 +90,35 @@ QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )
mGrassDataType = mInfo["TYPE"].toInt();
QgsDebugMsg( "mGrassDataType = " + QString::number( mGrassDataType ) );

// 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
if ( mGrassDataType == CELL_TYPE )
{
//limit: -2147483647;
mNoDataValue = -2000000000;
}
else if ( mGrassDataType == DCELL_TYPE )
{
// Don't use numeric limits, raster layer is using
// qAbs( myValue - mNoDataValue ) <= TINY_VALUE
// if the mNoDataValue would be a limit, the subtraction could overflow.
// No data value is shown in GUI, use some nice number.
// Choose values with small representation error.
// limit: 1.7976931348623157e+308
mNoDataValue = -1e+300;
}
else
{
if ( mGrassDataType != FCELL_TYPE )
{
QgsDebugMsg( "unexpected data type" );
}

// limit: 3.40282347e+38
mNoDataValue = -1e+30;
}
QgsDebugMsg( QString( "mNoDataValue = %1" ).arg( mNoDataValue ) );

// TODO: refresh mRows and mCols if raster was rewritten
// We have to decide some reasonable block size, not to big to occupate too much
// memory, not too small to result in too many calls to readBlock -> qgis.d.rast
Expand Down Expand Up @@ -258,36 +287,7 @@ void QgsGrassRasterProvider::readBlock( int bandNo, QgsRectangle const & viewEx

double QgsGrassRasterProvider::noDataValue() const
{
double nul;
// 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
if ( mGrassDataType == CELL_TYPE )
{
//limit: -2147483647;
nul = -2000000000;
}
else if ( mGrassDataType == DCELL_TYPE )
{
// Don't use numeric limits, raster layer is using
// qAbs( myValue - mNoDataValue ) <= TINY_VALUE
// if the mNoDataValue would be a limit, the subtraction could overflow.
// No data value is shown in GUI, use some nice number.
// Choose values with small representation error.
// limit: 1.7976931348623157e+308
nul = -1e+300;
}
else
{
if ( mGrassDataType != FCELL_TYPE )
{
QgsDebugMsg( "unexpected data type" );
}

// limit: 3.40282347e+38
nul = -1e+30;
}
QgsDebugMsg( QString( "noDataValue = %1" ).arg( nul ) );
return nul;
return mNoDataValue;
}

double QgsGrassRasterProvider::minimumValue( int bandNo ) const
Expand Down
2 changes: 2 additions & 0 deletions src/providers/grass/qgsgrassrasterprovider.h
Expand Up @@ -256,6 +256,8 @@ class QgsGrassRasterProvider : public QgsRasterDataProvider
QgsCoordinateReferenceSystem mCrs;

QgsGrassRasterValue mRasterValue;

double mNoDataValue;
};

#endif

0 comments on commit 13a790d

Please sign in to comment.