Skip to content

Commit 4ae7b52

Browse files
committed
nodata rendered transparent
1 parent 5579962 commit 4ae7b52

8 files changed

+92
-9
lines changed

src/app/qgsrasterlayerproperties.cpp

+16-5
Original file line numberDiff line numberDiff line change
@@ -1298,9 +1298,9 @@ void QgsRasterLayerProperties::pixelSelected( const QgsPoint& canvasPoint )
12981298
mRasterLayer->identify( mMapCanvas->mapRenderer()->mapToLayerCoordinates( mRasterLayer, canvasPoint ), myPixelMap );
12991299

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

1303+
QList<double> values;
13041304
for ( int i = 0; i < bands.size(); ++i )
13051305
{
13061306
QMap< int, QString >::const_iterator pixelResult = myPixelMap.find( bands.at( i ) );
@@ -1309,20 +1309,31 @@ void QgsRasterLayerProperties::pixelSelected( const QgsPoint& canvasPoint )
13091309
QString value = pixelResult.value();
13101310
if ( value != tr( "out of extent" ) )
13111311
{
1312-
setTransparencyCell( tableTransparency->rowCount() - 1, i, value.toDouble() );
1312+
QgsDebugMsg( QString( "Is it %1 of band %2 nodata?" ).arg( value ).arg( bands.at( i ) ) );
1313+
if ( value == tr( "null (no data)" ) || // Very bad! TODO: improve identify
1314+
mRasterLayer->dataProvider()->isNoDataValue( bands.at( i ), value.toDouble() ) )
1315+
{
1316+
return; // Dont add nodata, transparent anyway
1317+
}
1318+
values.append( value.toDouble() );
13131319
}
13141320
}
13151321
}
13161322
if ( bands.size() == 1 )
13171323
{
13181324
// Set 'to'
1319-
setTransparencyCell( tableTransparency->rowCount() - 1, 1, transparencyCellValue( tableTransparency->rowCount() - 1, 0 ) );
1325+
values.insert( 1, values.value( 0 ) );
13201326
}
1327+
tableTransparency->insertRow( tableTransparency->rowCount() );
1328+
for ( int i = 0; i < values.size(); i++ )
1329+
{
1330+
setTransparencyCell( tableTransparency->rowCount() - 1, i, values.value( i ) );
1331+
}
1332+
setTransparencyCell( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, 100 );
13211333
}
13221334

13231335
tableTransparency->resizeColumnsToContents();
13241336
tableTransparency->resizeRowsToContents();
1325-
delete renderer;
13261337
}
13271338

13281339
void QgsRasterLayerProperties::sliderTransparency_valueChanged( int theValue )

src/core/raster/qgsmultibandcolorrenderer.cpp

+21-1
Original file line numberDiff line numberDiff line change
@@ -234,22 +234,42 @@ void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & e
234234
redVal = readValue( redData, redType, currentRasterPos );
235235
greenVal = readValue( greenData, greenType, currentRasterPos );
236236
blueVal = readValue( blueData, blueType, currentRasterPos );
237-
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
237+
if ( mInput->isNoDataValue( mRedBand, redVal ) ||
238+
mInput->isNoDataValue( mGreenBand, greenVal ) ||
239+
mInput->isNoDataValue( mBlueBand, blueVal ) )
240+
{
241+
imageScanLine[j] = defaultColor;
242+
}
243+
else
244+
{
245+
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
246+
}
247+
238248
++currentRasterPos;
239249
continue;
240250
}
241251

252+
bool isNoData = false;
242253
if ( mRedBand > 0 )
243254
{
244255
redVal = readValue( redData, redType, currentRasterPos );
256+
if ( mInput->isNoDataValue( mRedBand, redVal ) ) isNoData = true;
245257
}
246258
if ( mGreenBand > 0 )
247259
{
248260
greenVal = readValue( greenData, greenType, currentRasterPos );
261+
if ( mInput->isNoDataValue( mGreenBand, greenVal ) ) isNoData = true;
249262
}
250263
if ( mBlueBand > 0 )
251264
{
252265
blueVal = readValue( blueData, blueType, currentRasterPos );
266+
if ( mInput->isNoDataValue( mBlueBand, blueVal ) ) isNoData = true;
267+
}
268+
if ( isNoData )
269+
{
270+
imageScanLine[j] = defaultColor;
271+
++currentRasterPos;
272+
continue;
253273
}
254274

255275
//apply default color if red, green or blue not in displayable range

src/core/raster/qgspalettedrasterrenderer.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e
9393
{
9494
return 0;
9595
}
96+
QRgb myDefaultColor = qRgba( 0, 0, 0, 0 );
9697

9798
QgsRasterInterface::DataType transparencyType = QgsRasterInterface::UnknownDataType;
9899
if ( mAlphaBand > 0 )
@@ -129,6 +130,12 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e
129130
for ( int j = 0; j < width; ++j )
130131
{
131132
val = readValue( rasterData, rasterType, currentRasterPos );
133+
if ( mInput->isNoDataValue( mBandNumber, val ) )
134+
{
135+
imageScanLine[j] = myDefaultColor;
136+
++currentRasterPos;
137+
continue;
138+
}
132139
if ( !hasTransparency )
133140
{
134141
imageScanLine[j] = mColors[ val ].rgba();

src/core/raster/qgsrasterinterface.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,18 @@ QgsRasterInterface::DataType QgsRasterInterface::typeWithNoDataValue( DataType d
120120
return newDataType;
121121
}
122122

123+
inline bool QgsRasterInterface::isNoDataValue( int bandNo, double value ) const
124+
{
125+
// More precise would be qIsNaN(value) && qIsNaN(noDataValue(bandNo)), but probably
126+
// not important and slower
127+
if ( qIsNaN( value ) ||
128+
doubleNear( value, noDataValue( bandNo ) ) )
129+
{
130+
return true;
131+
}
132+
return false;
133+
}
134+
123135
// To give to an image preallocated memory is the only way to avoid memcpy
124136
// when we want to keep data but delete QImage
125137
QImage * QgsRasterInterface::createImage( int width, int height, QImage::Format format )

src/core/raster/qgsrasterinterface.h

+14
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,22 @@ class CORE_EXPORT QgsRasterInterface
125125
}
126126

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

131+
/** Return no data value for specific band. Each band/provider must have
132+
* no data value, if there is no one set in original data, provider decides one
133+
* possibly using wider data type.
134+
* @param bandNo band number
135+
* @return No data value */
136+
virtual double noDataValue( int bandNo ) const { Q_UNUSED( bandNo ); return noDataValue(); }
137+
138+
/** Test if value is nodata for specific band
139+
* @param bandNo band number
140+
* @param value tested value
141+
* @return true if value is nodata */
142+
virtual bool isNoDataValue( int bandNo, double value ) const ;
143+
130144
/** Read block of data using given extent and size.
131145
* Returns pointer to data.
132146
* Caller is responsible to free the memory returned.

src/core/raster/qgsrastertransparency.cpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,17 @@ bool QgsRasterTransparency::isEmpty( double nodataValue ) const
178178
{
179179
return (
180180
( mTransparentSingleValuePixelList.isEmpty() ||
181-
( mTransparentSingleValuePixelList.size() == 1 && doubleNear( mTransparentSingleValuePixelList.at( 0 ).min, nodataValue ) && doubleNear( mTransparentSingleValuePixelList.at( 0 ).max, nodataValue ) ) )
181+
( mTransparentSingleValuePixelList.size() == 1 &&
182+
( doubleNear( mTransparentSingleValuePixelList.at( 0 ).min, nodataValue ) ||
183+
doubleNear( mTransparentSingleValuePixelList.at( 0 ).max, nodataValue ) ||
184+
( nodataValue > mTransparentSingleValuePixelList.at( 0 ).min &&
185+
nodataValue < mTransparentSingleValuePixelList.at( 0 ).max ) ) ) )
182186
&&
183187
( mTransparentThreeValuePixelList.isEmpty() ||
184-
( mTransparentThreeValuePixelList.size() < 4 && doubleNear( mTransparentThreeValuePixelList.at( 0 ).red, nodataValue ) &&
185-
doubleNear( mTransparentThreeValuePixelList.at( 0 ).green, nodataValue ) && doubleNear( mTransparentThreeValuePixelList.at( 0 ).blue, nodataValue ) ) ) );
188+
( mTransparentThreeValuePixelList.size() == 1 &&
189+
doubleNear( mTransparentThreeValuePixelList.at( 0 ).red, nodataValue ) &&
190+
doubleNear( mTransparentThreeValuePixelList.at( 0 ).green, nodataValue ) &&
191+
doubleNear( mTransparentThreeValuePixelList.at( 0 ).blue, nodataValue ) ) ) );
186192
}
187193

188194
void QgsRasterTransparency::writeXML( QDomDocument& doc, QDomElement& parentElem ) const

src/core/raster/qgssinglebandgrayrenderer.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ void * QgsSingleBandGrayRenderer::readBlock( int bandNo, QgsRectangle const & e
118118
{
119119
grayVal = readValue( rasterData, rasterType, currentRasterPos );
120120

121+
if ( mInput->isNoDataValue( mGrayBand, grayVal ) )
122+
{
123+
imageScanLine[j] = myDefaultColor;
124+
++currentRasterPos;
125+
continue;
126+
}
127+
121128
//alpha
122129
currentAlpha = mOpacity;
123130
if ( mRasterTransparency )

src/core/raster/qgssinglebandpseudocolorrenderer.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ void * QgsSingleBandPseudoColorRenderer::readBlock( int bandNo, QgsRectangle co
117117
for ( int j = 0; j < width; ++j )
118118
{
119119
val = readValue( rasterData, rasterType, currentRasterPos );
120+
if ( mInput->isNoDataValue( mBand, val ) )
121+
{
122+
imageScanLine[j] = myDefaultColor;
123+
++currentRasterPos;
124+
continue;
125+
}
120126
if ( !mShader->shade( val, &red, &green, &blue ) )
121127
{
122128
imageScanLine[j] = myDefaultColor;

0 commit comments

Comments
 (0)