diff --git a/src/providers/wms/qgswmsprovider.cpp b/src/providers/wms/qgswmsprovider.cpp index 23dd711987b..0ed161b8eb4 100644 --- a/src/providers/wms/qgswmsprovider.cpp +++ b/src/providers/wms/qgswmsprovider.cpp @@ -4844,19 +4844,26 @@ QGISEXTERN QgsProviderMetadata *providerMetadataFactory() } #endif -Qgis::DataType QgsWmsInterpretationConverter::dataType() const -{ - return Qgis::DataType::Float32; -} std::unique_ptr QgsWmsInterpretationConverter::createConverter( const QString &key ) { if ( key == QgsWmsInterpretationConverterMapTilerTerrainRGB::interpretationKey() ) return std::make_unique(); + else if ( key == QgsWmsInterpretationConverterTerrariumRGB::interpretationKey() ) + return std::make_unique(); return nullptr; } +Qgis::DataType QgsWmsInterpretationConverter::dataType() const +{ + return Qgis::DataType::Float32; +} + +// +// QgsWmsInterpretationConverterMapTilerTerrainRGB +// + void QgsWmsInterpretationConverterMapTilerTerrainRGB::convert( const QRgb &color, float *converted ) const { int R = qRed( color ); @@ -4879,3 +4886,36 @@ QgsRasterHistogram QgsWmsInterpretationConverterMapTilerTerrainRGB::histogram( i { return QgsRasterHistogram(); } + +// +// QgsWmsInterpretationConverterTerrariumRGB +// + +void QgsWmsInterpretationConverterTerrariumRGB::convert( const QRgb &color, float *converted ) const +{ + // for description of the "terrarium" format: + // https://github.com/tilezen/joerd/blob/master/docs/formats.md + + if ( qAlpha( color ) == 255 ) + { + *converted = qRed( color ) * 256 + qGreen( color ) + qBlue( color ) / 256.f - 32768; + } + else + { + *converted = std::numeric_limits::quiet_NaN(); + } +} + +QgsRasterBandStats QgsWmsInterpretationConverterTerrariumRGB::statistics( int, int, const QgsRectangle &, int, QgsRasterBlockFeedback * ) const +{ + QgsRasterBandStats stat; + stat.minimumValue = -11000; + stat.maximumValue = 9000; + stat.statsGathered = QgsRasterBandStats::Min | QgsRasterBandStats::Max; + return stat; +} + +QgsRasterHistogram QgsWmsInterpretationConverterTerrariumRGB::histogram( int, int, double, double, const QgsRectangle &, int, bool, QgsRasterBlockFeedback * ) const +{ + return QgsRasterHistogram(); +} diff --git a/src/providers/wms/qgswmsprovider.h b/src/providers/wms/qgswmsprovider.h index faa06d57f46..071bdabc1af 100644 --- a/src/providers/wms/qgswmsprovider.h +++ b/src/providers/wms/qgswmsprovider.h @@ -156,6 +156,30 @@ class QgsWmsInterpretationConverterMapTilerTerrainRGB : public QgsWmsInterpretat static QString interpretationKey() {return QStringLiteral( "maptilerterrain" );} }; +//! Class to convert color to float value following the terrarium terrain RGB interpretation +class QgsWmsInterpretationConverterTerrariumRGB : public QgsWmsInterpretationConverter +{ + public: + void convert( const QRgb &color, float *converted ) const override; + + QgsRasterBandStats statistics( int bandNo, + int stats = QgsRasterBandStats::All, + const QgsRectangle &extent = QgsRectangle(), + int sampleSize = 0, QgsRasterBlockFeedback *feedback = nullptr ) const override; + + QgsRasterHistogram histogram( int bandNo, + int binCount = 0, + double minimum = std::numeric_limits::quiet_NaN(), + double maximum = std::numeric_limits::quiet_NaN(), + const QgsRectangle &extent = QgsRectangle(), + int sampleSize = 0, + bool includeOutOfRange = false, + QgsRasterBlockFeedback *feedback = nullptr ) const override; + + static QString displayName() {return QObject::tr( "Terrarium Terrain RGB" );} + static QString interpretationKey() {return QStringLiteral( "terrariumterrain" );} +}; + /** * * \brief Data provider for OGC WMS layers. diff --git a/src/providers/wms/qgswmssourceselect.cpp b/src/providers/wms/qgswmssourceselect.cpp index 9a905dece31..68e04875329 100644 --- a/src/providers/wms/qgswmssourceselect.cpp +++ b/src/providers/wms/qgswmssourceselect.cpp @@ -1322,6 +1322,7 @@ QgsWmsInterpretationComboBox::QgsWmsInterpretationComboBox( QWidget *parent ): Q { addItem( tr( "Default" ), QString() ); addItem( QgsWmsInterpretationConverterMapTilerTerrainRGB::displayName(), QgsWmsInterpretationConverterMapTilerTerrainRGB::interpretationKey() ); + addItem( QgsWmsInterpretationConverterTerrariumRGB::displayName(), QgsWmsInterpretationConverterTerrariumRGB::interpretationKey() ); } void QgsWmsInterpretationComboBox::setInterpretation( const QString &interpretationKey ) diff --git a/tests/src/providers/testqgswmsprovider.cpp b/tests/src/providers/testqgswmsprovider.cpp index 9b65641360b..6ad00f8d894 100644 --- a/tests/src/providers/testqgswmsprovider.cpp +++ b/tests/src/providers/testqgswmsprovider.cpp @@ -26,6 +26,8 @@ #include #include #include +#include "qgssinglebandgrayrenderer.h" +#include "qgsrasterlayer.h" /** * \ingroup UnitTests @@ -271,6 +273,34 @@ class TestQgsWmsProvider: public QObject QVERIFY( imageCheck( "convert_value", mapSettings ) ); } + void testTerrariumInterpretation() + { + QString dataDir( TEST_DATA_DIR ); + + QgsXyzConnection xyzConn; + xyzConn.interpretation = QgsWmsInterpretationConverterTerrariumRGB::interpretationKey(); + xyzConn.url = QUrl::fromLocalFile( dataDir + QStringLiteral( "/terrarium_terrain_rgb.png" ) ).toString(); + QgsRasterLayer layer( xyzConn.encodedUri(), "terrain", "wms" ); + QVERIFY( layer.isValid() ); + QVERIFY( layer.dataProvider()->dataType( 1 ) == Qgis::DataType::Float32 ); + + QgsSingleBandGrayRenderer *renderer = new QgsSingleBandGrayRenderer( layer.dataProvider(), 1 ); + QgsContrastEnhancement *e = new QgsContrastEnhancement( Qgis::DataType::Float32 ); + e->setMinimumValue( -50 ); + e->setMaximumValue( 50 ); + e->setContrastEnhancementAlgorithm( QgsContrastEnhancement::StretchToMinimumMaximum ); + renderer->setContrastEnhancement( e ); + layer.setRenderer( renderer ); + + QgsMapSettings mapSettings; + mapSettings.setLayers( QList() << &layer ); + mapSettings.setExtent( layer.extent() ); + mapSettings.setOutputSize( QSize( 400, 400 ) ); + mapSettings.setOutputDpi( 96 ); + mapSettings.setDpiTarget( 48 ); + QVERIFY( imageCheck( "terrarium_terrain", mapSettings ) ); + } + bool imageCheck( const QString &testType, QgsMapSettings &mapSettings ) { //use the QgsRenderChecker test utility class to diff --git a/tests/testdata/control_images/wmsprovider/expected_convert_value/expected_convert_value_mask.png b/tests/testdata/control_images/wmsprovider/expected_convert_value/expected_convert_value_mask.png new file mode 100644 index 00000000000..35dfd225cac Binary files /dev/null and b/tests/testdata/control_images/wmsprovider/expected_convert_value/expected_convert_value_mask.png differ diff --git a/tests/testdata/control_images/wmsprovider/expected_terrarium_terrain/expected_terrarium_terrain.png b/tests/testdata/control_images/wmsprovider/expected_terrarium_terrain/expected_terrarium_terrain.png new file mode 100644 index 00000000000..4e06ce46e7d Binary files /dev/null and b/tests/testdata/control_images/wmsprovider/expected_terrarium_terrain/expected_terrarium_terrain.png differ diff --git a/tests/testdata/terrarium_terrain_rgb.png b/tests/testdata/terrarium_terrain_rgb.png new file mode 100644 index 00000000000..f0830198ecb Binary files /dev/null and b/tests/testdata/terrarium_terrain_rgb.png differ