Skip to content

Commit 603365c

Browse files
committedApr 3, 2017
Fix some crashes in paletted raster renderer
- handle negative color values - don't crash when calculating unique values in bad rasters
1 parent 1cbe971 commit 603365c

File tree

4 files changed

+4530
-32
lines changed

4 files changed

+4530
-32
lines changed
 

‎src/core/raster/qgspalettedrasterrenderer.cpp

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,6 @@ QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterInterface *input,
3535
updateArrays();
3636
}
3737

38-
QgsPalettedRasterRenderer::~QgsPalettedRasterRenderer()
39-
{
40-
delete[] mColors;
41-
delete[] mIsNoData;
42-
}
43-
4438
QgsPalettedRasterRenderer *QgsPalettedRasterRenderer::clone() const
4539
{
4640
QgsPalettedRasterRenderer *renderer = new QgsPalettedRasterRenderer( nullptr, mBand, mClassData );
@@ -181,15 +175,15 @@ QgsRasterBlock *QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle cons
181175
continue;
182176
}
183177
int val = ( int ) inputBlock->value( i );
184-
if ( val > mMaxColorIndex || mIsNoData[ val ] )
178+
if ( !mColors.contains( val ) )
185179
{
186180
outputData[i] = myDefaultColor;
187181
continue;
188182
}
189183

190184
if ( !hasTransparency )
191185
{
192-
outputData[i] = mColors[val];
186+
outputData[i] = mColors.value( val );
193187
}
194188
else
195189
{
@@ -203,7 +197,7 @@ QgsRasterBlock *QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle cons
203197
currentOpacity *= alphaBlock->value( i ) / 255.0;
204198
}
205199

206-
QRgb c = mColors[val];
200+
QRgb c = mColors.value( val );
207201
outputData[i] = qRgba( currentOpacity * qRed( c ), currentOpacity * qGreen( c ), currentOpacity * qBlue( c ), currentOpacity * qAlpha( c ) );
208202
}
209203
}
@@ -415,6 +409,8 @@ QgsPalettedRasterRenderer::ClassData QgsPalettedRasterRenderer::classDataFromRas
415409
double max = stats.maximumValue;
416410
// need count of every individual value
417411
int bins = ceil( max - min ) + 1;
412+
if ( bins <= 0 )
413+
return ClassData();
418414

419415
QgsRasterHistogram histogram = raster->histogram( bandNumber, bins, min, max, QgsRectangle(), 0, false, feedback );
420416
if ( feedback && feedback->isCanceled() )
@@ -453,26 +449,12 @@ QgsPalettedRasterRenderer::ClassData QgsPalettedRasterRenderer::classDataFromRas
453449

454450
void QgsPalettedRasterRenderer::updateArrays()
455451
{
456-
// find maximum color index
457-
ClassData::const_iterator mIt = mClassData.constBegin();
458-
for ( ; mIt != mClassData.constEnd(); ++mIt )
459-
{
460-
mMaxColorIndex = qMax( mMaxColorIndex, mIt->value );
461-
}
462-
mMaxColorIndex = qMax( 0, mMaxColorIndex );
463-
464-
delete [] mColors;
465-
delete [] mIsNoData;
466-
mColors = new QRgb[mMaxColorIndex + 1];
467-
mIsNoData = new bool[mMaxColorIndex + 1];
468-
std::fill( mIsNoData, mIsNoData + mMaxColorIndex, true );
469-
452+
mColors.clear();
470453
int i = 0;
471454
ClassData::const_iterator it = mClassData.constBegin();
472455
for ( ; it != mClassData.constEnd(); ++it )
473456
{
474-
mColors[ it->value] = qPremultiply( it->color.rgba() );
475-
mIsNoData[it->value] = false;
457+
mColors[it->value] = qPremultiply( it->color.rgba() );
476458
i++;
477459
}
478460
}

‎src/core/raster/qgspalettedrasterrenderer.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer
6060
* Constructor for QgsPalettedRasterRenderer.
6161
*/
6262
QgsPalettedRasterRenderer( QgsRasterInterface *input, int bandNumber, const ClassData &classes );
63-
~QgsPalettedRasterRenderer();
6463

6564
//! QgsPalettedRasterRenderer cannot be copied. Use clone() instead.
6665
QgsPalettedRasterRenderer( const QgsPalettedRasterRenderer & ) = delete;
@@ -146,15 +145,13 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer
146145
private:
147146

148147
int mBand;
149-
int mMaxColorIndex = -INT_MAX;
150148
ClassData mClassData;
151149

152150
//! Source color ramp
153151
std::unique_ptr<QgsColorRamp> mSourceColorRamp;
154152

155-
//! Premultiplied color array
156-
QRgb *mColors = nullptr;
157-
bool *mIsNoData = nullptr;
153+
//! Premultiplied color map
154+
QMap< int, QRgb > mColors;
158155
void updateArrays();
159156
};
160157

‎tests/src/python/test_qgsrasterlayer.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,8 +589,7 @@ def testPalettedClassDataFromLayer(self):
589589
self.assertEqual(classes[9].label, '10')
590590

591591
# bad band
592-
with self.assertRaises(Exception):
593-
classes = QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 10101010)
592+
self.assertFalse(QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 10101010))
594593

595594
# with ramp
596595
r = QgsGradientColorRamp(QColor(200, 0, 0, 100), QColor(0, 200, 0, 200))
@@ -618,6 +617,32 @@ def testPalettedClassDataFromLayer(self):
618617
expected = [11, 21, 22, 24, 31, 82, 2002, 2004, 2014, 2019, 2027, 2029, 2030, 2080, 2081, 2082, 2088, 2092, 2097, 2098, 2099, 2105, 2108, 2110, 2114, 2118, 2126, 2152, 2184, 2220]
619618
self.assertEqual([c.value for c in classes], expected)
620619

620+
# bad layer
621+
path = os.path.join(unitTestDataPath('raster'),
622+
'hub13263.vrt')
623+
info = QFileInfo(path)
624+
base_name = info.baseName()
625+
layer = QgsRasterLayer(path, base_name)
626+
classes = QgsPalettedRasterRenderer.classDataFromRaster(layer.dataProvider(), 1)
627+
self.assertFalse(classes)
628+
629+
def testPalettedRendererWithNegativeColorValue(self):
630+
""" test paletted raster renderer with negative values in color table"""
631+
632+
path = os.path.join(unitTestDataPath('raster'),
633+
'hub13263.vrt')
634+
info = QFileInfo(path)
635+
base_name = info.baseName()
636+
layer = QgsRasterLayer(path, base_name)
637+
self.assertTrue(layer.isValid(), 'Raster not loaded: {}'.format(path))
638+
639+
renderer = QgsPalettedRasterRenderer(layer.dataProvider(), 1,
640+
[QgsPalettedRasterRenderer.Class(-1, QColor(0, 255, 0), 'class 2'),
641+
QgsPalettedRasterRenderer.Class(3, QColor(255, 0, 0), 'class 1')])
642+
643+
self.assertEqual(renderer.nColors(), 2)
644+
self.assertEqual(renderer.usesBands(), [1])
645+
621646

622647
if __name__ == '__main__':
623648
unittest.main()

‎tests/testdata/raster/hub13263.vrt

Lines changed: 4494 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.