nodata rendered transparent

This commit is contained in:
Radim Blazek 2012-08-23 16:48:00 +02:00
parent 5579962fb0
commit 4ae7b522ab
8 changed files with 92 additions and 9 deletions

View File

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

View File

@ -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

View File

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

View File

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

View File

@ -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.

View File

@ -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

View File

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

View File

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